Page 1 sur 1

réflexion sur la réflexion

Publié : sam. 27/juin/2015 8:23
par Guillot
Image

en fouinant sur le site j'ai vu que je suis pas le premier a me casser les dents sur la réflexion
point de vue géométrie c'est pourtant simple:
créer une camera "miroir" symétrique à la camera principale par rapport au plan de reflexion
et plaquer la texture (venant de CreateRenderTexture de la camera miroir) (inversé) sur le mesh
le problème c'est qu'il faut faire un plaquage 2D tout bête et la je vois pas comment m'y prendre
j'ai pallier à ce problème "segmentant" le mesh du miroir et en mettant à jour les coordonnées UV
ça fait un effet un peu crado si on regarde le miroir de façon "rasante"
ça s’atténue en augmentant le nombre de facette

mais c'est vexant de faire tous ce ça alors qu'y des matières dans les scriptes Ogres qui font ce genre de truc tres bien
genre "SphereMap/SphereMappedRustySteel"
ou la fonction EntityCubeMapTexture qui fait bien plus balaise

je sais pas si vous comprendrez quelque chose à mes explications un peu rapides

j'ai fait 2 fonctions, une pour un miroir limité et l'autre pour un miroir illimité (pour faire le reflet sur un lac)
(la première présente un défaut sur les bords à cause de CameraDirection qui retourne -1 quand on sort de l'écran)

Code : Tout sélectionner

;reflexion - Pf shadoko - 2015 

EnableExplicit

Global.w ex,ey,dx,dx1,dy,dy1,nb,typemiroir=1
Global Dim e(19)

Procedure.f POM(v.f)
  ProcedureReturn (Random(v*1000)-v*500)/500
EndProcedure

Procedure limite(V, i, s)
  If V < i :ProcedureReturn i:EndIf
  If V > s :ProcedureReturn s:EndIf
  ProcedureReturn V
EndProcedure

Procedure scene()
  Protected i,j,k,c,x,y,dx=8,dy=8
  Protected nbs=8,nbf=6
  
  Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/desert.zip", #PB_3DArchive_Zip)
  Parse3DScripts()
  
  ;######################################## cameras 
  ;principale
  CreateCamera(0, 0, 0, 100, 100):MoveCamera(0, 2000, 500, 0, #PB_Absolute):CameraLookAt(0, 0, 100, 0):CameraBackColor(0, $ff4444) 
  ;miroir
  CreateCamera(1, 0, 0,50,50):CameraBackColor(1, $ff4444)
  SkyBox("desert07.jpg")
  CreateLight(0,$ffffff, 10000, 10000, 5000)
  AmbientColor($222222)
  
  ;######################################## textures  
  CreateTexture(0,512,512)
  StartDrawing(TextureOutput(0))
  For i=0 To 1000
    Line(Random(511),0,1,511,RGB(255,Random(255),128))
    Line(0,Random(511),511,1,RGB(Random(255),255,0))
  Next
  StopDrawing()
  
  CreateTexture(1,512,512)
  StartDrawing(TextureOutput(1))
  For i=0 To 1000
    Line(Random(511),0,1,511,RGB(128,255,Random(255)))
    Line(0,Random(511),511,1,RGB(0,128,Random(255)))
  Next
  StopDrawing()
    
  CreateRenderTexture(10,CameraID(1),ex,ey)
  
  ;######################################## material
  CreateMaterial(0, TextureID(0)) 
  CreateMaterial(1, TextureID(1))  
  CreateMaterial(10, TextureID(10)):SetMaterialColor(10,#PB_Material_AmbientColor,$ff0000)
  
  ;######################################## mesh  
  CreateSphere(0,64)  
  CreatePlane(1,2000,2000,16,16,1,1)  
  CreateSphere(3,128)
   
  ;######################################## entity
  Define h.f
  
  CreateEntity(1, MeshID(1), MaterialID(10),0,0,0,1)
   
  For i=0 To 19:e(i)=CreateEntity(-1, MeshID(0), MaterialID(0),0,0,0,1):Next
  
  For i=1 To 40
    h=1+pom(0.5)
    c= CreateEntity(-1, MeshID(3), MaterialID(1),pom(2000),128*h,pom(2000),1)
    ScaleEntity(c,1+pom(0.5),h,1+pom(0.5))
  Next 
EndProcedure

Procedure rendermirror1(mesh,camP,camM)
  Protected i,j,c,cy1,cy2,px,py,r
  Protected.f x,y,z,xp,yp,zp,xd,yd,zd,d
  Protected Dim T.PB_MeshVertex(0)
  xp=CameraX(camP):xd=CameraDirectionX(camP)
  yp=CameraY(camP):yd=CameraDirectionY(camP)
  zp=CameraZ(camP):zd=CameraDirectionZ(camP)
  CameraDirection(camM,xd,-yd,zd)
  MoveCamera(camM,xp,-yp,zp,#PB_Absolute)
  r=yp*500
  cy1=limite(CameraProjectionY(camP,xp+xd*r,0,zp+zd*r),0,ey-1)
  GetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate,0,MeshVertexCount(mesh)-1):c=-1
  For j=0 To 16           :py=cy1+j*(ey-1-cy1)/16
    For i=16 To 0 Step -1:px=i*(ex-1)/16
      PointPick(camP,px,py):x=PickX():y=PickY():z=PickZ()
      d=-yp/y
      c+1
      With t(c)
        \u=px/ex
        \v=1-py/ey
        \x=x*d+xp
        \y=y*d+yp
        \z=z*d+zp
      EndWith
    Next
  Next
  SetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate,0,MeshVertexCount(mesh)-1)
EndProcedure

Procedure rendermirror2(mesh,camP,camM)
  Protected c,n,mx,my
  Protected.f xp,yp,zp,xd,yd,zd
  Protected Dim T.PB_MeshVertex(0)
  
  xp=CameraX(camP):xd=CameraDirectionX(camP)
  yp=CameraY(camP):yd=CameraDirectionY(camP)
  zp=CameraZ(camP):zd=CameraDirectionZ(camP)
  CameraDirection(camM,xd,-yd,zd)
  MoveCamera(camM,xp,-yp,zp,#PB_Absolute)
  mx=ex   ;CameraViewWidth (camM) ;marche pas,
  my=ey   ;CameraViewHeight(camM) ;pas compris !
  n=MeshVertexCount(mesh)-1
  GetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate ,0,n)
  For c=0 To n
    With t(c)
      \u=  CameraProjectionX(1,\x, 0,\z)/mx
      \v=  CameraProjectionY(1,\x, 0,\z)/my
    EndWith
  Next
  SetMeshData(mesh,0,t(),#PB_Mesh_Vertex|#PB_Mesh_UVCoordinate,0,MeshVertexCount(mesh)-1)
EndProcedure


Define.f KeyX, KeyY,keyz, MouseX, MouseY,time,v,a,x,y,z,r.l
Define i,j,c,px,py,p
InitEngine3D()   
InitSprite()
InitKeyboard()
InitMouse()
OpenWindow(0, 0, 0, 0,0, "reflexion",#PB_Window_Maximize)
ex=WindowWidth (0,#PB_Window_InnerCoordinate)
ey=WindowHeight(0,#PB_Window_InnerCoordinate)
OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)

Macro DT(t1,t2)
  DrawText(4,p,t1)
  DrawText(60,p,t2)
  p+16
EndMacro
CreateSprite(0,120,170,#PB_Sprite_AlphaBlending)
StartDrawing(SpriteOutput(0))
DrawingMode(#PB_2DDrawing_AlphaClip|#PB_2DDrawing_Outlined )
Box(0,0,120,170)
BackColor($0000ff)
dt("Déplacements:","")
dt("[Left]","")
dt("[Right]","")
dt("[Up]","")
dt("[Down]","")
dt("Mouse+wheel","")
dt("","")
dt("Commandes:","")
dt("[F1]","Limité")
dt("[F2]","Ilimité")
StopDrawing()

scene()

Repeat    
  For i=0 To 19:MoveEntity(e(i),Cos(Radian(time+18*i))*400,64+Abs(Cos(Radian(i*36+time*10)))*100,Sin(Radian(time+18*i))*400,#PB_Absolute):RotateEntity(e(i),time+i*20,time+i*20,time+i*20):Next

  WindowEvent()
  
  ExamineMouse()
  MouseX = -MouseDeltaX() *  0.05
  MouseY = -MouseDeltaY() *  0.05
  ExamineKeyboard()
  keyx=(-Bool(KeyboardPushed(#PB_Key_Left)<>0)+Bool(KeyboardPushed(#PB_Key_Right)<>0))*4
  keyz=(-Bool(KeyboardPushed(#PB_Key_Down)<>0)+Bool(KeyboardPushed(#PB_Key_Up   )<>0))*4+MouseWheel()*50
  RotateCamera(0, MouseY, MouseX, 0, #PB_Relative):MoveCamera  (0, KeyX, keyy, -keyz)
  
  If KeyboardPushed(#PB_Key_F1):CreatePlane(1,2000,2000,16,16,1,1):CreateEntity(1, MeshID(1), MaterialID(10),0,0,0,1):typemiroir=1:EndIf
  If KeyboardPushed(#PB_Key_F2):CreatePlane(1,2000,2000,16,16,1,1):CreateEntity(1, MeshID(1), MaterialID(10),0,0,0,1):typemiroir=2:EndIf
  
  Select typemiroir
      Case 1:rendermirror1(1,0,1)
      Case 2:rendermirror2(1,0,1)
  EndSelect  
  time+RenderWorld()/200
  DisplayTransparentSprite(0, 8,8,128)
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)

End


Re: réflexion sur la réflexion

Publié : sam. 27/juin/2015 9:20
par falsam
A peine arrivé et tu nous présente un second code fonctionnel.

Que ce soit miroir limité ou illimité, il y a effectivement des défauts. En illimité par exemple, si on déplace la souris à droite ou le plus à gauche, le miroir disparaît subitement.

En tout cas bravo !

Puisque tu as fouiné dans le forum (ça c'est bien car beaucoup ne le font pas) tu as du trouver mon expérimentation sur le miroir.

A lire pour ceux qui ne l'ont pas encore fait: http://www.purebasic.fr/french/viewtopi ... 10#p169710 le code que je présente est lui aussi fonctionnel.

Visiblement tu ne sais plus comment tu as connu PureBasic.

Allez deux autres questions :
- Tu connaissais Ogre avant PureBasic ?
- Pourquoi Pf shadoko sur tes deux codes ?

Et pour finir : Vivement ton prochain code :)

Re: réflexion sur la réflexion

Publié : sam. 27/juin/2015 9:52
par falsam
Puisqu'on est en pleine réflexion, pourquoi cette ligne mettant en oeuvre la variable timer ?

Code : Tout sélectionner

time+RenderWorld()/200

Re: réflexion sur la réflexion

Publié : sam. 27/juin/2015 16:08
par Guillot
salut falsam

les réponses:
- ouai y'a un bug, mais il est pas propre au miroir, quand le centre de l'entity sort de l'écran l'entity disparait
j'ai vu qu'en mettant ça dans une statiquegeometry le bug disparait .mais faut que je me penche la dessus...
- ouai, je l'ai vu, j'ai même vu beaucoup de tes codes (souvent tres didactique si je me souviens bien)
- comment j'ai connu PB : tu vas rire
la 1er fois en cherchant une doc sur GDI+, elle était destiné à PB, mais elle m'a bien servi pour VB6
la 2eme fois en cherchant un langage pour Android (no comment), c'est là que je l'ai essayé, j'ai vite mordu à l'hameçon
- non, je connaissais pas ogre, mais avant PB, je ne m'interessais pas à la 3d modernes (je pensais qu'y avait plus rien d'interessant à programmer (erreur !) sinon y'a bien longtemps, ça me passionnais, (faire mes routine de texture en assembleur, optimisé à donf). j'avais fais un moteur 3d à la doom sur amiga (amospro+devpac(je crois))
- la bonne question : je me suis gouré en remplissant mon compte, j'ai mis mon nom au lieu du pseudo (pf shadoko), pas resussi à corriger ni à supprimer mon compte pour le refaire, ça m'agonflé, j'ai laissé béton en me disant que je corrigerai ça plus tard...
si quelqu'un à la solution, je suis preneur
- renderworld renvoit le tps écoulé depuis la derniere frame, je le cumule et je l'utilise pour l'animation des boules qui tourne (comme ça ça tourne à la même vitesse quelque soit le nombre de FPS)

voilà, voilà

Re: réflexion sur la réflexion

Publié : sam. 27/juin/2015 16:18
par G-Rom
ouai y'a un bug, mais il est pas propre au miroir, quand le centre de l'entity sort de l'écran l'entity disparait
C'est pas un bug , c'est une feature , il faut mettre à jour la bounding box de l'entité. UpdateMeshBoundingBox() , si le pb persiste, c'est un bug.

Re: réflexion sur la réflexion

Publié : sam. 27/juin/2015 22:07
par Guillot
merci g-rom
ça fonctionne

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 0:10
par crisot
Je ne connais encore absolument pas PB donc je ne peux pas déchiffrer clairement ton code ni identifier dedans ce qui cause ton souci. En revanche, les symptomes de cet effet "vaguelette" sont clairs, c'est un problème de correction de perspective. Si on descend le nombre de tiles à 1x1 au lieu de 16x16, qu'on se met en mode F2, et qu'on regarde le plan miroir avec une vue pas trop rasante sur la tranche, on voit très clairement sur les 2 triangles qui composent le plan qu'il n'y a pas de correction de perspective.

Il faut chercher le problème dans la projection. (je cherche, je cherche, mais comme je connais pas PB, c'est pas si simple ^ ^)

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 0:15
par crisot
En fait il faudrait faire ce rendu de miroir non pas sur une texture plaquée sur un plan, mais directement dans le buffer, en délimitant le traçage à ce plan. Ca revient à changer le "frustum", mais à priori PB ne sait point faire (en tout cas je ne trouve pas sur google).

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 8:10
par G-Rom
Non, PB ne sait pas faire, la seul chose qui marcherais , c'est les shaders.

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 15:32
par Ollivier
Il y a un juste milieu entre le faisable et l'impossible.
Il faut savoir ce que l'on veut avec certitude et pragmatisme, et déterminer ce dont on dispose sur le plan technique.

Un miroir absolu est faisable en "trichant" (on double les éléments "physiquement", le moteur traite le rendu, juste faire gaffe que si la chambre est derrière le miroir de la salle de bain, il faut afficher le reflet du lavabo quand on est dans la salle de bain, et l'effacer avant d'atteindre la chambre, sinon on se retrouve avec le reflet du lavabo dans la chambre!!!).

Je n'ai pas d'ordi mais je me demande si Ogre ne permettrait pas plusieurs rendus (il me semble que si). Donc plusieurs reflets peuvent être créés. Les vagues d'un lacs sont répétitives. Le plus dur n'est pas leur reflet, mais le fait que la structure fil de fer d'une vague croisée (l'illusion d'optique nous fait prendre conscience systématiquement de 3 directions de vagues ni plus ni moins quand on regarde une étendue d'eau ventée) soit une grosse ch... à calculer (faisable mais pas en temps réel, donc prévoir une huitaine de structure fil de fer à "pré-calculer"). Enfin, ce qui est génial avec une étendue d'eau, c'est la nature logarithmique de la luminosité!

Résultat: 4 couleurs suffisent à représenter une surface dynamique liquide de manière absolument réaliste (l'oeil étant ébloui par l'une des 4 couleurs, il fait lui-même le dégradé entre les 3 autres plus sombres et tout cela dans un mouvement permanent).

En fait, si c'est une image "parfaite", c'est impossible en temps réel. Il faut "tricher" (s'éloigner des perfections mathématiques) pour obtenir le résultat voulu. Il faut savoir si un caillou doit être lancé dans l'eau, il faut savoir quelle est la forme de l'étendue d'eau (circulaire, quelconque, fractale, pour les "rebonds" de ride).

L'eau, c'est un vrai m...ier à calculer!!! Donc bon courage (encore que c'est un cro-magnon du matériel info qui le dit donc j'ignore les éventuelles solutions matérielles).

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 16:31
par crisot
Ou sinon utiliser le plan miroir comme stencil buffer, mais là encore je ne crois pas que PB fasse.

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 17:14
par G-Rom
Tu as la fonction EnableCameraReflexion(CameraID) dans engine3D.dll

Code : Tout sélectionner

OpenLibrary(0,"Engine3D.dll")
PrototypeC EnableCameraReflection(cameraID)
Global EnableCameraReflection.EnableCameraReflection = GetFunction(0,"PBO_EnableCameraReflection")
L'idée était de rendre une camera dans une texture , puis de l'afficher sur un plan ( obligatoirement horizontal ) la fonction créer une réflexion sur l'axe Y.
il te faut donc 2 camera, une retournée qui rend dans une RTT, l'autre celle qui rend ta scène.
evidement, il te faudra le bon .material pour le rendu de la texture à l'envers, il ne suffira pas de l'appliqué bêtement sur un plan , c'est pas évident à mettre en place , c'est surement pour cela que la fonction en question n'a pas été "releasé" ;)

Re: réflexion sur la réflexion

Publié : lun. 29/juin/2015 18:54
par comtois
G-Rom a écrit :c'est pas évident à mettre en place , c'est surement pour cela que la fonction en question n'a pas été "releasé" ;)
En effet j'avais fait quelques tests, mais je n'avais pas un bon résultat. Si je trouve un peu de motivation et surtout du temps, je referai une série de tests pour chercher ce qui clochait.