Normal mapping.

Généralités sur la programmation 3D
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Normal mapping.

Message par crisot »

Hello, pour les besoin d'une poignée d'entre vous j'ai écris un loader de fichier Wavefront (.OBJ) pour pouvoir importer des mesh facilement.

Il n'est pas encore partageable mais pour le moment j'arrive à charger des objets texturés. Sauf que voilà , aujourd'hui le minimum pour avoir un rendu acceptable, c'est une diffuse map et une normal map pour donner du détail. Hors, je ne trouve pas comment passer une normal map à PB avec le système de texture / material par defaut. Pour garder un code simple et partageable je souhaiterais rester sur les fonctions de base, sans passer par un shader.

Quelqu'un sait il donc comment faire des materiaux "avancés" avec PB/Ogre sans shaders?
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

Bonjour Crisot, le rendu avec une normale map s'effectue toujours dans le cadre d'un fragment shader, comment veut tu qu'en dehors d'un shader le moteur devine la normale d'un pixel ?
tu peu charger ton shader via une datasection par ex, et faire de mémoire un material à la main , et bien sur, ne pas oublié de calculé les tangentes de ton mesh.
je vais chécker tout ce que je viens de te dire , je reviendrais ici.
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

C'est bien ca, je me suis juste trompé sur le chargement du shader en datasection, pas possible, c'est la que je m'aperçois qu'il manque plein de fonction pour les materiaux et que tu coup, c'est une plaie pour jouer avec le moteur.


edit:

http://wiki.ogre3d.org/Materials#Advanced_Materials
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Normal mapping.

Message par crisot »

G-Rom a écrit :Bonjour Crisot, le rendu avec une normale map s'effectue toujours dans le cadre d'un fragment shader
J'aurais du m'y attendre... :) Donc: Non, le normal mapping existait avant les shaders :)
G-Rom a écrit :comment veut tu qu'en dehors d'un shader le moteur devine la normale d'un pixel ?
Une normale map est justement une texture qui contient la normale de chaque pixel, où RGB remplacent XYZ. Le GPU les combine avec un produit en croix (DOT3RGB) pour obtenir un rendu de luminescence en greyscale, puis on module cela après une texture colorée (diffuse map). C'est même fait la seule technique d'éclairage au pixel disponible sans shaders.

Ce que je demande, c'est si PB / Ogre permettent d'accéder à ce combiner DOT3RGB sans passer par un shader, pas pour la beauté du geste, simplement pour avoir un code de démo minimaliste et simple.

Je vais mater le Wiki sur les Advanced Materials merci :)
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

J'aurais du m'y attendre... :) Donc: Non, le normal mapping existait avant les shaders :)
Oui, j'ai fait un peu de "demoscene" ou j'utilisait une heightmap pour extraire les normales de chaque pixels.
C'est même fait la seule technique d'éclairage au pixel disponible sans shaders.
Même si tu as accès a ce "combiner", il te faut une ou des sources lumineuses , car avoir la normal map + la diffuse map ne suffit pas à avoir un éclairage cohérent sous ogre.
je ne pense pas qu'en dehors d'un shader ogre puissent faire ce genre de rendu.

la formule de tête en pseudo glsl :
float diffuse_normal = dot ( normal(UV) , light_dir )
vec4 fragment_color = vec4( diffuse.rgb * diffuse_normal , diffuse.a )
"light_dir" et le vecteur normalisé entre ton pixel et la lumière et "normal(UV)" la valeur de ta normalmap au coordonée courante du fragment shader

je ne pense pas que tu puisse mélanger des techniques de "demomaker" avec ogre.
j'ai quand même cherché ici au cas ou :
https://www.ogre3d.org/docs/manual18/manual_17.html
rien trouvé.
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Normal mapping.

Message par crisot »

A priori ce serait tout de même possible via un material script, mais autant écrire un shaders, l'idée était vraiment de savoir si c'était possible aussi simplement qu'en OpenGL (texture_unit0 normalmap DOT3RGB texture_unit1 diffusemap modulate).

Bon, je vais m'en tenir à faire la preview de l'OBJ avec une simple diffuse. Tant pis c'est moche, au moins Falsam aura son loader d'OBJ. :)

Merci.

Edit: De toute façon du coup j'aurais quand même du taper du code pour créer les tangentes et binormals, petit oublie de ma part. Ca allait déjà contre l'idée d'avoir une belle preview en 2 lignes de code.
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

j'ai essayé avec un script :
material grom/test
{
technique
{
pass
{
texture_unit
{
texture Metal_Plate_019a_Base_Color.jpg

}

texture_unit
{
texture Metal_Plate_019a_Normal.jpg
colour_op_ex (modulate ou dotproduct) src_current source1
}

}
}
}
marche pas bien évidement. :)
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Normal mapping.

Message par crisot »

Je ne connais pas ce type de script (la solution est très probablement là dedans), mais effectivement, ça ne peut pas marcher: En fixed pipeline (=sans shader), une normal map se met ->TOUJOURS<- sur l'unit 0 :)

Là sur l'unit 1 de tête je dirais qu'en modulate tu as un arc en ciel, en dot product tu dois avoir une image en noir et blanc (ce qui signifirait que c'est effectivement possible).
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

Alors, ogre, n'utilise pas les fonctions du style glVertex , glColor , etc... ou l'équivalent en DX , ensuite pour l'unit 0 et la normal map, je ne sais pas d'ou tu sort cela , dans le .material vu plus haut
la premiere "passe" est la diffuse ,la seconde la normale modulé avec la première passe.
pour le résultat que tu annonces , c'est à peu près cela , mais l'inverse , modulate n&b , et dotp , pas arc en ciel , mais un mix entre les 2.
le ffp d'ogre fait les shaders de base à la volée (comme beaucoup de moteur évolué) en fonction de ton matérial si tu ne fourni pas toi même un shader, dans tout les cas, il y a un shader de compilé quelque part.

https://ogrecave.github.io/ogre/api/1.11/rtss.html
https://ogrecave.github.io/ogre/api/1.1 ... ation.html

Sinon, de tête, tu n'étais pas loin du résultat ;)
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Normal mapping.

Message par crisot »

Si Ogre créé un shader, effectivement c'est très différent.

Pour la normal map impérativement sur l'unit 0, c'est lié au fonctionnement du fixed pipeline. Lorsque l'on dotproduct l'unit 1, malheureusement, le pipeline ne dotproduct pas la texture de l'unit 1 avant de moduler par l'unité 0 mais après. On dotproduct donc unit1 x unit0 quoi qu'il arrive et non juste unit1 -> résultat en greyscale.

Du coup en fixed pipeline la seule solution est de mettre la normalmap sur l'unit0 -> dotproduct -> sortie en greyscale, puis modulation avec l'unit1 (colorisation par diffuse map).

Après c'est un faux problème, c'est juste une déformation de ma part, je code 98% du temps sur AmigaOs sans accès aux shaders, j'ai bien trop pris l'habitude de bosser "the old way" par obligation :) (mais pour le coup je la maitrise assez convenablement donc normalement il est assez rare que je raconte des bêtises sur "l'avant shaders" :) ).

Si les scripts génèrent un shader quoi qu'il arrive, ça devrait régler le souci...
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

crisot a écrit :Si Ogre créé un shader, effectivement c'est très différent.

Pour la normal map impérativement sur l'unit 0, c'est lié au fonctionnement du fixed pipeline. Lorsque l'on dotproduct l'unit 1, malheureusement, le pipeline ne dotproduct pas la texture de l'unit 1 avant de moduler par l'unité 0 mais après. On dotproduct donc unit1 x unit0 quoi qu'il arrive et non juste unit1 -> résultat en greyscale.

Du coup en fixed pipeline la seule solution est de mettre la normalmap sur l'unit0 -> dotproduct -> sortie en greyscale, puis modulation avec l'unit1 (colorisation par diffuse map).

Après c'est un faux problème, c'est juste une déformation de ma part, je code 98% du temps sur AmigaOs sans accès aux shaders, j'ai bien trop pris l'habitude de bosser "the old way" par obligation :) (mais pour le coup je la maitrise assez convenablement donc normalement il est assez rare que je raconte des bêtises sur "l'avant shaders" :) ).

Si les scripts génèrent un shader quoi qu'il arrive, ça devrait régler le souci...
Quand tu me parles des units, je fait un bon en arrière de quelques années , ca me rappelle le fixed pipeline de l'opengl à papa avec des units limité , mais des vieux et vague souvenir... :D
Les scripts génère bien un shader, mais un shader "générique" , donc limité , avec la nouvelle version d'ogre , j'ai vu que le moteur gère en natif le PBR mais sous opengl ( pas compatible ogre / windows / purebasic malheureusement )
ce qui résoudrais ton problème de rendu.

Pour la génération de shader à la volée , imagine le nombre de carte , l'api que tu utilises ( ogre gère entre autre : dx,ogl,gles2,3,cg,vulkan?,etc... ) donc le moteur doit gérer la création de shader pour tout les backend de rendu , géré aussi les extentions dispo entre les différentes carte graphique , etc... je te laisse imaginer l'usine derrière cela, c'est titanesque.
Avatar de l’utilisateur
Guillot
Messages : 522
Inscription : jeu. 25/juin/2015 16:18

Re: Normal mapping.

Message par Guillot »

dans la derniere version (5.71 b2) j'ai fais ajouter aux scripts materiels des exemples un script generique (utilisant MaterialTextureAliases) pour le normal mapping
hélas, il ne fonctionne que sous windows
j'ai lancer un appel contribution pour ajouter des scripts génèrique, mais pour l'instant rien...
https://www.purebasic.fr/english/viewto ... 36&t=72594

ci dessous un exemple d'utilisation
(il comporte une fonction pour creer une normal map a partir de la luminosité des pixels)

Code : Tout sélectionner

; ----------------------------------------------------------------------------------------------------------
;   MaterialTextureAliases
;
;   This demo work only on Windows (Script HLSL)
; ----------------------------------------------------------------------------------------------------------

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Procedure.f lng3D(*v.Vector3)
  ProcedureReturn Sqr(*V\x * *V\x + *V\y * *V\y + *V\z * *V\z)
EndProcedure

Procedure Norme3D(*V.Vector3,l.f=1)
  Protected.f lm = l / lng3d(*v)
  *V\x * lm
  *V\y * lm
  *V\z * lm  
EndProcedure

Procedure.i textureArray2NM(texture,Array hm.l(2),amplitude.f)
  Protected i,j,n,dx,dy,h00,h10,h01
  Protected.f x,y,z,l, max=255/amplitude,max2=max*max
  Protected.vector3 p
  
  dx=ArraySize(hm(),2)+1
  dy=ArraySize(hm(),1)+1
  Dim bmp.l(dy-1,dx-1)
  For j=0 To dy-1
    For i=0 To dx-1
      h00=hm(j,i)
      h10=hm(j,(i+1) % dx)
      h01=hm((j+1) % dy,i)
      p\x=h00-h10
      p\y=h00-h01
      l=p\x*p\x+p\y*p\y:If l>max2:l=max2:EndIf
      p\z=Sqr(max2-l)
      Norme3D(p,127)
      bmp(j,i)=RGBA(p\z+128,p\y+128,p\x+128,255)
    Next
  Next  
  n=CreateTexture(texture,dx,dy):If texture=-1:texture=n:EndIf
  StartDrawing(TextureOutput(texture)):CopyMemory(@bmp(0,0),DrawingBuffer(),dx*dy*4):StopDrawing()
  ProcedureReturn texture
EndProcedure

Procedure.i textureHM2NM(imgNM,imgHM,amplitude.f)
  Protected i,j,dx,dy,c
  
  StartDrawing(TextureOutput(imgHM))
  dx=OutputWidth()
  dy=OutputHeight()
  Dim hm.l(dy-1,dx-1)
  Dim bmp.l(dy-1,dx-1)
  CopyMemory(DrawingBuffer(),@bmp(0,0),dx*dy*4)
  StopDrawing()
  For j=0 To dy-1
    For i=0 To dx-1
      c=bmp(j,i)
      hm(j,i)=Red(c)+Green(c)+Blue(c)
    Next
  Next
  ProcedureReturn textureArray2NM(imgNM,hm(),amplitude/3)
EndProcedure

;>>>>>>>>>>>>>>>>>>>> BUG GetScriptMaterial <<<<<<<<<<<<<<<<<<<<
Procedure.i GetScriptMaterial_(material.i,name.s)
  Protected m,mtemp=GetScriptMaterial(-1,name)
  m=CopyMaterial(mtemp,material)
  If material=-1:material=m:EndIf
  FreeMaterial(mtemp)
  ProcedureReturn material
EndProcedure
Macro GetScriptMaterial(material,name):GetScriptMaterial_(material,name):EndMacro
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

#MeshNumber=4
#Gap=4
Define i, a.f,ai.f

InitEngine3D(#PB_Engine3D_DebugLog):InitSprite():InitKeyboard():InitMouse()
ExamineDesktops()
ex=DesktopWidth (0)
ey=DesktopHeight(0)
OpenWindow(0, 0,0, ex,ey, "MaterialTextureAliases -  [Esc] quit",#PB_Window_Maximize)
OpenWindowedScreen(WindowID(0), 0, 0, ex, ey, 0, 0, 0)

Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/scripts/MaterialScripts_Generic", #PB_3DArchive_FileSystem ) 
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Parse3DScripts()

;--------------------------------------- scene ---------------------------------------

CreateCamera(0, 0, 0, 100, 100):MoveCamera(0,0,10,-4):CameraLookAt(0,0,0,0)

CreateLight(0, $ffffff, 0, 4, 0):SetLightColor(0,#PB_Light_SpecularColor, $ffffff)
AmbientColor($222222)

LoadTexture(1,"ValetCoeur.jpg")
LoadTexture(2,"Wood.jpg")
LoadTexture(3,"grass.jpg")
LoadTexture(4,"MRAMOR6X6.jpg")

CreateCube(1,3)
CreateSphere(2,2,32,32)
CreateTorus(3,1.5,1,32,32)
CreateCylinder(4,2,4,32,1,1)

For i=1 To #MeshNumber
  BuildMeshTangents(i)
  textureHM2NM(10+i,i,4)
  GetScriptMaterial(i,"ParallaxOcclusionMapping")
  MaterialTextureAliases(i,TextureID(i),TextureID(10+i),0,0)
  MaterialFilteringMode(i,#PB_Material_Anisotropic,4)
  CreateEntity(i,MeshID(i),MaterialID(i))
  RotateEntity(i,Random(360),Random(360),Random(360))
Next

Repeat
  While WindowEvent():Wend
  ExamineMouse()
  ExamineKeyboard()
  a+0.005
  For i=1 To #MeshNumber
    ai=a+i*2*#PI/#MeshNumber
    MoveEntity(i,#Gap *Cos(ai),0,#Gap *Sin(ai),#PB_Absolute)
    RotateEntity(i,0.2,0.3,0.5,#PB_Relative)
  Next
  RenderWorld()
  FlipBuffers()    
Until MouseButton(#PB_MouseButton_Left) Or KeyboardReleased(#PB_Key_Escape)
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

Salut, Ogre n'en fourni pas assez ?
https://github.com/OGRECave/ogre/blob/m ... d.material

je crois même qu'il y a le dot3 pour crisot dedans ;)
Avatar de l’utilisateur
Guillot
Messages : 522
Inscription : jeu. 25/juin/2015 16:18

Re: Normal mapping.

Message par Guillot »

j'ai essayé de faire tourner ceux des exemples le la 1.8
j'en ai fais fonctionner correctement aucun (hormis ceux nececssitant CG (que je prefererai eviter))
(peut etre qu'il manquait des info aux mesh de test (couche de texture par exemple)
note : la prochaine version de PB integrera les texture 1d et 3d (je parle des cubemap et non des texture volumique)

en fait par contribution, j'attend des materiaux clé en main (avec exemple), à l'image de ce qu'a fait samuel entre autre
je connais tres mal les shaders, certain son bien plus compétant que moi dans le domaine
j'ai pas mal de boulot par ailleurs en 3D
bref, j'espere que quelqu'un va se donner un peu de mal
(avec MaterialTextureAliases on pourra rendre ces materiaux generique, de plus la dans prochaine version il y aura également une fonction pour spécifier des parametres shader)
G-Rom
Messages : 3626
Inscription : dim. 10/janv./2010 5:29

Re: Normal mapping.

Message par G-Rom »

C'est ton prochain objectif , c'est les matériaux , ce que je comprendrais , abandonne tout de suite les matériaux actuel.
Ogre ( en 1.8 ) fourni a prioris , j'ai pas plus creusé que cela , le rendu PBR , qui est une sorte de "révolution" dans les domaines, des matériaux...
je veut dire par là , que c'est une sorte de normalisation , plus de diffuse , de spécular , etc... mais place à l'albedo , le roughness , le metallic , évidement dit comme cela, c'est pas très clair.
mais avec cette technique , tu peu avoir n'importe quel type de rendu 3D réaliste ou pas, ces des gars de chez pixar qui on mis cela en place, les nouveaux engine ( même les anciens ) s'y mettent , c'est pas pour rien.
le rendu est vraiment super.

Quand je veut faire de la 3D, je joue avec Godot engine que je maitrise pas mal , voila le genre de rendu que tu pourrais avoir sous Ogre , ici c'est fait avec le fameux godot :
https://www.youtube.com/watch?v=Rvbp4jv2S7Q
Si tu regarde bien la démo , tu vois plein de mesh aligné , le casque , les sorte de "webcam" , ils utilise en fait le même matérial , avec des réglage différents , d'ou la force du PBR qui couvre 99% des matériaux ( ca inclus les normal maps & cie ... )

encore du rendu PBR :
https://www.youtube.com/watch?v=IQCpcw84hhQ


Ha , et tant que j'y suis , j'ai un occulus Rift , je peu faire l'import du SDK , il faudrais juste un coup de pate pour avoir accès aux textures native des cameras & des matrices de transformation & je pourrais l'adapté pour faire un couple PB/rift.
Répondre