réflexion sur la réflexion

Généralités sur la programmation 3D
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

réflexion sur la réflexion

Message 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

Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: réflexion sur la réflexion

Message 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 :)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7323
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: réflexion sur la réflexion

Message 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
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: réflexion sur la réflexion

Message 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à
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: réflexion sur la réflexion

Message 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.
Avatar de l’utilisateur
Guillot
Messages : 672
Inscription : jeu. 25/juin/2015 16:18

Re: réflexion sur la réflexion

Message par Guillot »

merci g-rom
ça fonctionne
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: réflexion sur la réflexion

Message 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 ^ ^)
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: réflexion sur la réflexion

Message 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).
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: réflexion sur la réflexion

Message par G-Rom »

Non, PB ne sait pas faire, la seul chose qui marcherais , c'est les shaders.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: réflexion sur la réflexion

Message 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).
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: réflexion sur la réflexion

Message par crisot »

Ou sinon utiliser le plan miroir comme stencil buffer, mais là encore je ne crois pas que PB fasse.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: réflexion sur la réflexion

Message 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é" ;)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: réflexion sur la réflexion

Message 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.
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Répondre