Voici une autre image plus claire mais aussi plus ancienne.
Voici une autre image plus claire mais aussi plus ancienne.
vraiment pas mal du tout, tu ne pourrais pas fournir la petite demo pour qu'on puisse mieux l'apprecier ?
Si tu le souhaites je peux l'heberger pour que les autres puissent la telecherger si tu ne peux pas
Ce serait vraiment tres gentil de ta part.
Des que je realise une demo, je te contacte par MP, ca te va ?
ha oui... effectivement ca rend super bien... beau boulot
Merci loka et bafman.
Voici un autre shot :
Merci tout le monde de vous interresser toujours à ce topic, néamoins, il faut noter que l'on s'est éloigné du sujet, et ce topic est devenu une sorte de page d'actualité : je viens de faire ceci, j'ai ajouté cela, etc... Don, n'abusons pas de ce forum et recentrons la discussion.
(Avant de passer à autre chose, je vous demande votre clémence pour juger les shots, je ne suis pas un artiste ;-) !
Quand je me suis lancé dans cette tache (titanesque), tout le monde n'arretait pas de me dire : Tu n'y arriveras jamais, et même si tu y arrives, ca ne pourra pas concurrencer des produits déja existants telque OGRE etc... : Je leurs reponds que ce n'est pas mon but, mon etait de :
1- mettre au point une architecture extensible, intuitive et puissante.
2- approfondir mes connaissance dans le domaine de 3D, notamment en OpenGL.
J'ai pas mal bossé la dessus, et sur quelques points, je crois que j'ai pleinement réussi, surtout sur des points architectureaux, quand à ce qui concerne l'API 3D (OpenGL), je n'y ai pas consacré beaucoup d'effort, ca peut venir ensuite.
Je vais maintenant presenter en gros l'architecture de toodee (mon moteur).
Les objets de base sont :
- Mesh : stocke la géometrie d'un objet.
- Shader : Définit la façon dont on remplit une surface.
- PrimaryController : un objet qui permet de faire des translations, rotations et des scales via une interface intuitive (méthode translate, rotate...)
- SecondaryController : un objet qui permet de faire des translations, rotations et des scales mais pas directement, je veux dire pas via des méthodes, mais via des controlleurs comme le SinController. Pour expliquer, il s'agit d'une liste de Point3Controller, ce dernier est compose de 3 FloatController : X, Y, Z. Il y'a quelques FloatControllers prédéfinis comme le Sin, Cos, Triangle, Sawtooth, Noise, ..., et vous pouvez en ajouter de nouveaux. Grace à ce système qui a l'air très compliqué, on peut automatiser une animation complexe, par exemple un objet qui tourne continuellement et qui vibre etc...
- Gizmo : composé d'un PrimaryController et d'un SecondaryController.
- Object : Un objet en toodee est une liste de couples (Mesh, Shader) couplé avec un Gizmo pour le positionner. En fait il ne stocke pas le mesh et le shader, seulement leurs indices dans une liste globale.
- Font : Permet d'afficher du texte.
- Scene : une collection d'indices d'objets
- Camera : !!!!!!!!!!!!!!!
- World : une collection de scenes, de shaders, de meshes, de cameras, d'objets.
- Engine : le moteur, il contient tout.
On revient mnt à cette histoire d'indices : voici un exemple en pseudo code pour clarifier ce bordel :
J'espère que j'arrive à expliquer le principe. En procédant comme ceci, il n'y a pas de redondance. Un meme mesh ou shader peut être utilisé dans plusieurs objets. De plus, on peut créer plusieures scenes, et plusieures cameras, et choisir à tout instant quel scene dessiner et avec quelle camera. De plus, un même objet peut appartenir à plusieures scenes.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 VAR e : tdEngineI; s_id, m_id, o_id scene_id, camera_id : td_ui32; DEBUT e:=tdNewEngine;//On commence par créer le moteur //Ensuite, on le configure. e.Configure.SetParami(td_handle, Handle);//On lui indique le handle de la fenêtre e.Configure.SetParami(td_color_bits, 32);//etc... e.Startup;//initialise un contexte OpenGL et tous les champs s_id:=e.World.addShader;//On ajoute un shader, et on récupère son ID e.World.Shaders[s_id].load('shader1.shader');//On le charge depuis un fichier, regarder les messages precedants ! m_id:=e.World.addMesh;//On ajoute un mesh, et on récupère son ID e.World.Meshes[m_id].load('mesh1.mesh');//On le charge depuis un fichier, regarder les messages precedants ! o_id:=e.World.addObject;//On ajoute un objet, et on récupère son ID e.World.Objects[o_id].addCouple(s_id, m_id);//on ajoute autant de couples (shader, mesh) que l'in veut e.World.Objects[o_id].Gizmo.Primary.TranslateTo(50, 40, 30);//On le positionne via le controleur primaire scene_id:=e.world.addScene;//on crée une scene e.World.Scenes[scene_id].addObject(o_id);//on y insère notre objet camera_id:=e.world.addCamera;//on najoute une camera e.World.Cameras[camera_id].load('camera1.camera'); //on la charge depuis un ficher //Maintenant, pour effectuer un rendering, on appelle e.render(cmaera_id, scene_id);
C'est un peu compliqué, mais c'est robuste et très puissant.
Bon, j'ai une crampe aux mains, donc je vais arreter, et continuer plus tard pour expliquer plusieures autres aspects de toodee.
J'attends vos avis. Merci d'avance.
C'est beau
Continue comme ça !
Ouais c'est joli Continue comme ca, bon courage
encore très joli
Je comprend plutot bien le principe de ton moteur, ton explication (surtout la source) explique parfaitement comment l'utiliser et parait assez simple.
Bonjour tout le monde.
Ca y est ! La crampe des mains est partie ! Je vais donc pouvoir continuer de presenter les idées et les méthodes que j'ai utilisé dans toodee.
************** Les transformations das toodee ************
En re-lisant mon dernier post, J'ai vu que la partie concernant les controleurs (SecondaryController, FloatController, Point3Controller ...) etait du charabia, je vais donc re-expliquer la chose.
Je commence par le floatController.
C'est une classe dont voici l'entête :
C'est une classe abstraite, plus precisement c'est une interface (je bosse sur Delphi).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 tdFloatController = CLASSE PUBLIC PROCEDURE setParam(target: entier; value : réel); FONCTION transform(t:entier) : réel; FIN
la méthode setPAram permet de configurer le controlleur, et transform retourne une valeur selon la valeur de t (le temps) et des paramètres.
Par exemple, on peut définir une classe SinController qui implemente FloatController comme ceci :
Cette classe retourne une valeur qqui varie sinusoidalement selon t et dans l'intervalle [min..max]. Ce n'est qu'une possibilité, et je pense que via cette interface, les possiblitées sont infinies.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 tdSinController = classe PRIVEE min, max : réel; PUBLIC PROCEDURE setParam(target: entier; value : réel); DEBUT SI target = 0 ALORS min<-value SINON max<-value; FIN FONCTION transform(t:entier) : réel; DEBUT RETOURNER (max-min)*(sin(t)+1)/2; FIN FIN
Dans mon case, j'ai réalisé :
- Id controller :
Configuration:
target= 0 : la valeur (val).
fonctionnement:
Une fonction constante qui retourne val qlq soit t. (Waw ! Très ingénieux !)
- Sin controller :
Configuration:
target= 0 : la période (period).
target= 1 : le decalage (dec).
target= 2 : la borne inf (min).
target= 3 : la borne sup (max).
fonctionnement:
Une sinusoide de periode period retardé dans l'axe du temps de dec et bornée par min et max.
- Cos controller :
Configuration:
La même que SinController
fonctionnement:
Une fonction cosinus de periode period retardé dans l'axe du temps de dec et bornée par min et max.
- Triangle controller :
Configuration:
La même que SinController
fonctionnement:
Une fonction qui varie en triangle de periode period retardé dans l'axe du temps de dec et bornée par min et max.
- Square controller :
Configuration:
La même que SinController
fonctionnement:
Une fonction qui varie en carrée de periode period retardé dans l'axe du temps de dec et bornée par min et max.
- Sawtooth controller :
Configuration:
La même que SinController
fonctionnement:
Une fonction qui varie en dents de scie de periode period retardé dans l'axe du temps de dec et bornée par min et max.
- Noise controller :
Configuration:
target= 0 : le seed
target= 1 : la borne inf (min).
target= 2 : la borne sup (max).
fonctionnement:
retourne des valeurs aléatoires selon le seed et qui sont bornées par min et max.
On passe maintenant au choses sérieuses.
Une première classe qui utilise tout ce bordel mathématique est le Color4Controller. Elle est constitué de 4 FloatController et qui sont R, G, B et A.
Toute couleur dans toodee est en fait une instance de cette classe : La couleur d'arrière plan, les couleurs des vertices, etc...
De cette façon, et malgré la complexité avec la quelle se manipule les couleurs, on peut facilement créer des effets complexes et completement automatisés.
Vous n'avez pas à vous en soucier à chaque frame, en mettant à jour des variables ou à calculer de nouvelles valeurs ! Il faut juste tout initialiser et configurer au départ, et laisser le moteur s'en occuper pour la suite !
Une deuxième classe qui utilise ce qui precède est le Point3Controller. Elle est constitué de 3 FloatController et qui sont X, Y, Z. couplé à un champs type qui controlle quelle genre de modif cette classe effectue.
Le champs type est soit translate, rotate ou scale. Elle aussi permet de réaliser et d'automatiser beaucoup d'animations.
Un exemple : disons qu'on a une roue qui tourne autour de l'axe Z et qui se déplace sur l'axe des X.
On peut réaliser ce genre d'animations comme ceci : On associé à la roue 2 Point3Controllers : un pour la rotation, et un pour la translation.
-Pour le premier controleur (celui de la translation):
-On instancie le champs X (FloatController) par un SawTooth Controller (il a une une crète ascendante qui est linéaire), on
le configure comme ceci : une periode de 20s, un decalage de 0s, la valeur minimale est la position initiale de la roue et la valeur maximale est la position finale de la roue.
-On instancie les champs Y et Z (FloatController) par un IdController car La position Y et Z ne changent pas.
-On met le champs type à translate.
-Pour le second controleur (celui de la rotation):
-On instancie le champs Z (FloatController) par un SawTooth Controller (il a une crète ascendante qui est linéaire), on
le configure comme ceci : une periode de 5s, un decalage de 0s, une valeur minimale de 0° et une valeur maximale de 360°.
-On instancie les champs X et Y (FloatController) par un IdController car Les angles X et Y ne changent pas.
-On met le champs type à rotate.
Et on lance le rendering : La roue se déplace en tournat, et ce sans la moindre intervention de votre part !
Et puisque en géneral on aura besoin plus que d'un seul Point3Controller par objet, j'ai ajouté une nouvelle classe, Point3ControllerList qui permet de gérer une collection de Point3Controller !
C'est le SecondaryController.
RQ : L'effet du Point3Controller est relatif, pour que l'apport de chaque Point3Controller soit accumulé.
Malgré sa puissance, le SecondaryController reste difficile à manier, donc, pour simplifier la tache, j'ai ajouté une nouvelle classe : PrimaryController qui permet de positionner plus simplement les objets.
En gros, Elle contient les fonctions suivantes :
-TranslateTo(x, y, z)
-TranslateBy(mode, x, y, z) : mode est soit local soit global.
-RotateTo(x, y, z)
-RotateBy(mode, x, y, z) : mode est soit local soit global.
-ScaleTo(x, y, z)
-ScaleBy(x, y, z) : pas de mode encore (ca fonctionne en local, en global ça donne le shearing je pense).
Et enfin j'ai ajouté la classe Gizmo, qui est un couple (PrimaryController, SecondaryController).
Dans toodee, chaque objet, chaque texture, chaque Font, chaque Camera et chaque Light a son propre Gizmo. Je vous laiise imaginer ce qu'on peut réaliser avec tout ce bazar !
RQ : Les transformations sont appliqués dans cet ordre 1-Primary, 2-Secondary.
RQ2 : Je ne pretends pas avoir inventé tout cela, je me suis fortement inspiré de deux sources : 3D Studio Max et Quake III. Mais j'ai pas mal bossé ladessus quand même ;-)
************** Les shaders dans toodee ************
Je vous avertis tout de suite : Ne vous attendez pas à des prouesses du système de shading que j'ai développé ! Je suis un débutant dans le domaine, ma p****n de Radeon 9200 ne prend pas en charge les nouvelles technologie dans ce domaine.
Mais, on peut toujours réaliser de beaux effets avec !
Je vais commencer par presenter quelques classes intermédiaires avant d'attaquer les shaders.
J'ai réalisé une classes Texture qui permet de stocker et de manipuler une texture. En gros, il s'agit d'un wrapper des fonctions d'OpenGL.
Des méthodes pour charger une texture, pour changer le envmode, le wrap, bla bla bla ...
De plus, j'y ai ajouté :
1- La possibilité de stocker plusieures textures pour pouvoir réaliser des textures animées, donc tout le bazar des fonctions pour ajouter une nouvelle texture, passer d'une texture à l'autre quoi que ça peut se faire automatiquement.
J'explique : J'ai ajouté un champs Frequency, qui represente le temps au dela duquel on passe à l'image suivante. Mais si ce champs est à 0, le passage devient manuel et est à la charge du programmeur.
2- Un Gizmo : Pour pouvoir réaliser pleint d'effets sympas en jouant sur la matrice GL_TEXTURE.
Il y'a ensuite la classe ShaderPass, qui represente une passe lors du dessing d'un polygone.
Elle contient une Texture, Un Color4Controller pour pouvoir jouer un peu sur la couleur de la face ou modifier la couleur de la texture (dynamiquement).
Il y a aussi des fonctions pour controler le blending (toujours une abstaraction d'OpenGL) et enfin des fonctions pour controller l'etat de la passe (Marche/Arret).
Et enfin le shader, qui n'est autre qu'une collection de ShaderPass, pour pouvoir réaliser des effets plus complexes.
En fait, je pense que la puissance de ce système provient uniquement du gizmo de la texture et du Color4Controller de chaque ShaderPass, car ils permettent de réaliser des animations complexes et dynamiques avec un minimum d'efforts.
Comme je l'ai mentionné avant, je pense qu'il faut faire exposer tout ce qui est artistique aux artistes, et ce d'une manière simple.
Un artiste n'a pas à connaitre le langage de programmation surlequel on bosse, ni de connaitre les méthodes et les paramètres des classes du moteur.
Il faut donc trouver un moyen pour simplifier la tache aux artistes, et d'après ma connaissance, il y a 2 méthode pour ceci :
1- Soit développer un éditeur graphique de shaders, avec interface ergonomique, prévisualisation, etc... Mais c'est beaucoup de travail aux développeurs de réaliser un tel éditeur.
2- Soit développer un système de scripting qui permet de controler complètement un shader avec une syntaxe simple.
Je vous laisse deviner quelle option j'ai choisi !
J'ai donc réalisé une petite bibliothèque de scripting, qui permet de parser un script dans un langage que j'ai nommé BOSL pour Block Organized Scripting Language.
Dans ce langage, il y a deux structures :
- Une définition : dont voici la syntaxe
VARIABLE et VALEUR* sont une sequence qlq de caractères sans éspaces, car l'espace est utilisé comme séparatuer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part VARIABLE VALEUR [ VALEUR2 VALEUR3 ...] ;
Une définition se termine par un point virgule : (
- Un noeud : dont voici la syntaxe
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 OM { }
NOM est une sequence qlq de caractères sans éspaces.
Un noeud peut à son tour contenir un nombre quelquonque de définitions et d'autres noeuds. Pas d'ordre particulier.
Enfin, le fichier script est un fichier qui contient un seul noeud.(un peu comme XML).
RQ : Le BOSL accepte les commentaire sur une seule ligne du style C : //commentaire
exemple :
Revenons maintenant aux shaders.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 script_toto { //le noeud principal x 50;//une définition : x est la variable et 50 est la valeur. noeud_fils { //un noeud fils noeud_fils2{ //encore un fils du fils //un noeud peut être vide } } couleur 1 0 0; //une seconde définition : couleur est la varaible et 1, 0 et 0 sont les valeurs. }
Un script shader est un svript BOSL dont le neoud pricipal se nomme shader.
Dans ce noeud, il ne peut y avoir que des noeuds pass, qui representent un ShaderPass.
exemple :
C'est un shader simple qui se contente de remplir une surface avec le rouge.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 shader { pass { color{ r 1; b 0; g 0; a 1; } } }
Cette fois, ce shader remplit une surface avec une texture combinée à une couleur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 shader { pass { map default textures\texture1.jpg; color{ r 1; b 0.5; g 0.5; a 1; } } }
Le paramètre default indique au moteur d'utiliser son chargeur de texture par défaut. Il s'agit d'un wrapper autour de DEVIL. Merci les mecs !
Jusque la, les couleurs sont statiques. Utilisons les FloatControllers :
maintenant, la composante r de la couleur varie en sinus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 shader { pass { color{ r default sin 2000 0 0.2 1; b 0; g 0; a 1; } } }
le paramètre default indique que le controleur qu'on va spécifier (le sin) est un des controleurs fournies avec toodee.
ensuite le nom du controleur : sin, et la liste des paramètres pour configurer le controleur ( si vous ne suivez plus, revenez au post précedent sur les controleurs).
Voici maintenant un shader avec du blending et une texture animée :
maintenant, on va pouvoir jouer sur le gizmo de la texture :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 shader { pass { map default texture1.jpg texture2.bmp texture3.png texture4.gif texture5.pcx; //on specifie plusieures textures dans map pour créer une texture animée. frequency 250; //on change de texture tous les 250ms. blend on src_alpha one; //on controle le blend via la 1ière valur (on/off) //et la fonction du blend avec les valeurs 2 et 3. wrap repeat clamp; //on specifie le wrap mode valeur 1 = type du s-wrap //valeur 2 = type du t-wrap (clamp/repeat) magfilter linear; //on controle le magnefication //filternig (linear/nearest) minfilter linear_mipmap_linear; //on controle le minification filternig //(linear/nearest/linear_mipmap_linear //linear_mipmap_nearest/nearest_mipmap_linear/ //nearest_mipmap_nearesrt) envmode combine; //on controle envmmode : (combine/modulate/replace/add) color{ rgb 1; a default triangle 4000 50 0.5 1; } } }
on specifie le type de la transformation comme un neoud, et à l'interieur, on specifie les floatController pour chaque composante.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 shader { pass { map default textures\texture1.jpg; color{ r 1; b 0.5; g 0.5; a 1; } translate { s default sin 5000 0 -0.5 0.5; t default cos 5000 0 -0.5 0.5; } rotate { r default sawtooth 5000 0 -0.5 0.5; } scale { st default sin 5000 0 0.5 1; } } }
Si une composante est omise, son controlleur va toujours retouner 0, donc attention lors du scaling !
Un autre shader multipass
et ainsi de suite, la créativité est la seule limite !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 shader { pass { map default data\shaders\maps\font.jpg; minfilter linear_mipmap_nearest; magfilter nearest; envmode modulate; blend on zero 1-src_color; color { rgb 1; } } pass { map default data\shaders\maps\font.jpg; minfilter linear_mipmap_nearest; magfilter nearest; envmode modulate; blend on one one; color { rgb 1; } } }
Comme je le dis toujours, je ne pretends pas avoir inventé tout ceci ! je me suis fortement inspiré du dieu-le-tout-puissant John Carmack et de shaders de Quake III.
Une dernière chose, je pars en vacances demain, et je serais absent du forum pour au moins 2 semaines. Je m'excuse d'avance. D'ici là, j'espère que quelqu'un aurait pu lire mes deux precedants romans, je veux dire posts .
t'as pas a t'excuser parce que tu pars en vacance
Bon j'ai pas encore lu tout ça mais demain j'ai un peu de temp libre entre 2 cours.
surtout que j'ai vu le nom de John Carmack
Bon, je crois que ce topic est un peu mort là : il a assez vécu.
Mauvaise nouvelle : Je laisse tout omber ! Vu que Borland a laché Delphi et que j'ai juré de ne plus l'utiliser pour punir Borland, j'arrete tous mes projets : Quad3D et toodee.
Je suis actuellemnt en pleine transition vers C#, et une fois que je l'aurais bien maitrisé, je pense que je réamorcerais ces projets.
Je marque ce topic comme résolu pour laisser la place d'autres.
En attendant, et pour finir, merci à tous ceux qui ont participé à ce topic, vos réponses et avis m'ont beaucoup aidé.
Bonne chance, porter un code vers un autre langage n'est pas une mince affaire!
Reste calme et zen
Jc
Merci, et c'est vrai ce que tu dis, c'est trop décourageant, surtout avec les dizaines de milliers de lignes de code que j'ai déja pondue !
Oui je connais le problème... Tu perdras moins de temps à rassembler les grandes lignes de ton moteur courant et recoder tout à zéro.Envoyé par Modjo
Tu éviteras les grandes erreurs et tu seras sûrement capable d'améliorer le tout...
Jc
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager