Updater un fragment shader

Started by ariovistus, June 10, 2017, 07:25:56 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ariovistus

Hello. Tout d'abord félicitations pour le logiciel GeeXLab que j'avais découvert en 2007 sous le nom d'Hyperion. J'ai vu qu'il était possible d'utiliser des frame scripts en mode "live-coding" mais est-il également possible de faire la même chose avec les fragment shaders ? En gros je voudrais pouvoir ouvrir un fragment shader GLSL dans un editeur de texte, modifier une fonction compliquée dedans, le sauvegarder et que GeeXLab le relise à nouveau à partir du fichier pour tenir compte des modifications (sans avoir à fermer et à relancer GeeXLab).

En gros, j'ouvre le fragment shader et le frame script dans un éditeur texte et dans mon frame script je mets quelque chose comme :

var reload = 0
if (reload == 1) then
  //kill shader, reload shader from file
end
reload = 0

Si j'initialise reload à 1 au début du script, le shader est updaté juste une fois quand je le change, sinon il serait rechargé après chaque frame.

JeGX

Hyperion, ca fait bien longtemps! Effectivement GeeXLab est la version un peu plus moderne de l'ancetre Hyperion.

Dans la version actuelle de GeeXLab, le live-coding existe pour les scripts Lua/Python (essentiellement les scripts FRAMES) et les shaders GLSL.

Pour les scripts deux facons de live-coder sont disponibles (sous Windows):
1/ menu Tools > Open built-in script live-updater.
2/ en codant le script FRAME dans un fichier lua/py séparée et en ajoutant l'attribut update_from_file_every_frame="1" dans le node script en XML. Dès qu'un changement est fait dans le fichier, le script est mis à jour.  Une demo est dispo dans le code sample pack (gl-21/live-coding/live-coding-02.xml)

Pour les shaders, une seule facon de live-coder existe sous Windows:
1/ menu Tools > Open built-in GPU program live-updater.

Pourquoi la seconde facon de live-coder les shaders n'existe pas? Aucune idée!  Je vais regarder l'ajout de cette fonctionnalité très prochainement.

Sinon en attendant, essaies la technique que tu as évoquée. Pour éviter de reloader le shader à chaque frame, ajoute un petit délai entre deux reloading, genre 1 seconde.





ariovistus

Merci pour les infos ! J'avais complètement oublié de préciser que j'utilise exclusivement Linux sauf pour coder sous Visual Studio donc pas de menu pour moi. Existe-t-il une ligne de code magique en Lua sous GeexLab qui permet de charger (ou de recharger) un fragment shader à partir du fichier GLSL ?

L'idée c'est que dans un simple éditeur texte, j'ouvre le frame script Lua dans un onglet et le fragment shader GLSL dans un autre onglet pour piloter l'ensemble. Quand je fais une modif dans le shader, je sauvegarde le fichier puis dans le frame script Lua j'initialise la variable "reload" à 1 au début du script pour qu'il recharge le shader. Quand les changements sont pris en compte, j'initialise la variable à 0 et je sauvegarde à nouveau le frame script  pour qu'il arrête de recharger le shader.

Quote from: JeGX on June 11, 2017, 01:45:17 PM
Pourquoi la seconde facon de live-coder les shaders n'existe pas? Aucune idée!  Je vais regarder l'ajout de cette fonctionnalité très prochainement.
Ca serait génial  8)

JeGX

Je vais regarder le live-coding des shaders à partir d'un editeur de texte asap! J'aime bien cette facon simple et cross-platform pour bidouiller les shaders, c'est d'ailleurs pour ça que j'avais implémenté le live-coding des scripts à partir des fichiers.

Maintenant pour live-coder les shaders sous Linux il existe une autre solution: utiliser les outils de live-coding reseau avec Wine. J'avais testé cette technique au début de GeeXLab et à l'époque ça fonctionnait bien. Dans le répertoire GeeXLab/LiveUpdaters_Wine/ tu trouveras le binaire network_live_updater_glsl.exe.

J'ai si bonne mémoire, tu lances d'abord GeeXLab avec l'option pour démarrer le serveur TCP de live coding:


$ GeeXLab /start_tcpip_server /demofile="..."


Ensuite tu lances le network_live_updater_glsl.exe avec Wine:


$ wine ./network_live_updater_glsl.exe


Maintenant tu peux cliquer sur "Connect to GeeXLab" et normalement de là, tu obtiens la liste de tous les GPU programs. Tu sélectionnes un GPU program et tu peux le live coder.

Je viens de tester rapidement sous Windows et ca fonctionne. Dis moi ce qu'il en est sous Linux...

ariovistus

#4
Excellente interface ! J'ai fait comme tu as dit et le GPU Program Remote Updater (version 0.3.0) me place mon vertex shader dans la textbox "vertex shader" mais les trois quarts de mon pixel shader sont affichés dans la textbox "pixel shader" et le reste de mon pixel shader apparaît dans la textbox "geometry shader". La séparation de mon pixel shader a lieu en plein milieu d'une fonction.

Quand je modifie juste une variable dans la textbox "pixel shader", GeeXLab plante et quitte (et tout est ok dans les logs de GeeXLab) et le Remote Updater dit dans le log/output : Pixel shader ***ERROR***.

Quand je modifie juste une variable dans la textbox "geometry shader", GeeXLab ne plante pas mais le Remote Updater dit dans le log/output : Geometry shader ***ERROR***.

Je pense que ça marchera si GeeXLab met tout mon pixel shader dans la textbox "pixel shader" et rien dans la textbox "geometry shader".

Si tu veux que je fasse d'autres tests je suis OK ! En tout cas l'interface est bien pratique.

J'en profite pour te poser une question : si on appelle un frame script avec "update_from_file_every_frame="1"" et qu'on a 60 FPS, ça signifie 60 accès disque par seconde ? Dans ce cas j'imagine que ça serait mieux de mettre le frame script dans un ramdrive avant de l'ouvrir avec geexlab et un éditeur texte, comme ça les deux pointent vers la RAM au lieu du disque. Sinon il faudrait ajouter une option du style "number_of_frames_between_updates="60"" ou bien "number_of_seconds_between_updates="1"" avec la possibilité de changer l'int pour éviter trop d'accès disque.

PS : mon pixel shader fait 233 lignes. La textbox "pixel shader" contient les 179 premières lignes de mon pixel shader. A chaque fois que j'enlève une ligne vide de mon pixel shader et que je le sauvegarde avant de recommencer, je gagne un caractère de plus dans la textbox "pixel shader". Je crois que ton buffer de texte doit être trop court et que ça déborde dans la textbox "geometry shader"  :-\

JeGX

Ca m'aurait étonné que ca fonctionne bien ce truc! Je regarderai le code pourri de l'interface live-coding réseau un des ces quatres.

Pas grave, je suis en train d'ajouter le support live-coding des shaders depuis un editeur de texte et ca commence à fonctionner. Dès que c'est bon dans la version Windows, je compile une nouvelle version Linux.  Peut etre pour ce weekend :P

Quote from: ariovistus on June 14, 2017, 07:18:42 PM
J'en profite pour te poser une question : si on appelle un frame script avec "update_from_file_every_frame="1"" et qu'on a 60 FPS, ça signifie 60 accès disque par seconde ? Dans ce cas j'imagine que ça serait mieux de mettre le frame script dans un ramdrive avant de l'ouvrir avec geexlab et un éditeur texte, comme ça les deux pointent vers la RAM au lieu du disque. Sinon il faudrait ajouter une option du style "number_of_frames_between_updates="60"" ou bien "number_of_seconds_between_updates="1"" avec la possibilité de changer l'int pour éviter trop d'accès disque.

Oui dans la version actuelle, c'est assez bourrin, pour une scene à 60 FPS, le script est reloadé 60 fois par seconde. Je vais ajouter un petit délai paramétrable entre deux reloads.

ariovistus

#6
Que des bonnes news ! J'ai hâte de tester tout ça. Avec ce système, n'importe qui pourra utiliser son éditeur de texte préféré sur son OS préféré et piloter GeeXLab en live : les uniform dans le frame script ainsi que les shaders GLSL. Super pratique !

En attendant, je suis en train de finaliser mon logiciel de 3D pour visualiser et manipuler en temps-réel mes shaders avec plein de contrôles, boutons et sliders. C'est codé en c# pour l'interface graphique et ça utilise un wrapper OpenGL pour faire le rendu du GLSL. Hier j'ai fignolé la façon dont le contrôle OpenGL devait réagir lorsque je redimentionne la fenêtre et je me suis rendu compte que pas mal de logiciels OpenGL ne le faisaient pas correctement, dont GeeXLab   ::)

Si je lance un shader (disons qu'on fait juste le rendu d'une sphère) avec GeeXLab dans une fenêtre carrée, la sphère sera bien sphérique, centrée et cadrée. Si ensuite j'étire la fenêtre horizontalement, la sphère restera de la même taille et on verra juste davantage le fond comme un grand panorama. Mais, si au lieu d'étirer la fenêtre horizontalement je l'étire verticalement, alors la sphère va grandir et grandir proportionellement à la hauteur. Du coup elle n'est plus du tout cadrée horizontalement.

Je pense que ton code doit ressembler à ça :

gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();

double aspectRatio = 1.0;
if (clientHeight != 0  ) aspectRatio = ((double)(clientWidth) / (double)(clientHeight));
gl.glOrtho(-1.0 * aspectRatio, 1.0 * aspectRatio, -1.0, 1.0, -1.0, 1.0);

// Modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();


C'est à dire qu'il ne gère le redimensionnement correctement que pour un étirement horizontal. Si tu veux également gérer l'étirement vertical de la même façon, il faut faire ça :

gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();

double aspectRatio = 1.0;
if (clientHeight != 0  ) aspectRatio = ((double)(clientWidth) / (double)(clientHeight));
if (clientWidth <= clientHeight)
    gl.glOrtho(-1.0, 1.0, -1.0 / aspectRatio, 1.0 / aspectRatio, -1.0, 1.0);
else
    gl.glOrtho(-1.0 * aspectRatio, 1.0 * aspectRatio, -1.0, 1.0, -1.0, 1.0);

// Modelview matrix
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();


Essaie si tu as le temps et à mon avis ça devrait régler le problème  :)

JeGX

En fait GeeXLab ne gère pas directement le redimensionnement d'une fenetre. Lors d'un window resize, GeeXLab appelle un script de type SIZE et c'est au développeur de la demo de coder ce qu'il faut dedans. Donc tout dépend de ce que tu veux obtenir comme effet, si tu es en camera ortho (comme dans ton example) ou en camera perspective. Si le script est vide, le resize ne sera pas géré du tout.

ariovistus

Ca va alors, s'il suffit de le paramétrer dans le SIZE script. Sinon j'ai testé le plugin AntTweakBar dans GeeXLab et c'est très sympa pour le prototypage. C'est une bonne alternative au FRAME script en live-coding. Aujourd'hui, il me semble que c'est IMGUI qui soit à la mode mais AntTweakBar permet déjà de faire pas mal de choses  8)

JeGX

Le nouveau GeeXLab avec le live-coding des shaders GLSL depuis un fichier est dispo:
http://www.geeks3d.com/hacklab/20170618/geexlab-0-16-0-2-released-for-windows-and-linux-64-bit/


Comment utiliser la nouvelle technique de live-coding:
http://www.geeks3d.com/hacklab/20170618/new-way-to-live-code-glsl-shaders-in-geexlab-0-16/


Je n'ai pas fait des tests approfondis de cette nouvelle façon de live-coder, j'espère qu'il n'y aura pas trop de bugs.

ariovistus

#10
Excellent ! Je viens de le télécharger pour Linux et je te donnerai les résultats de mes tests  8)

ariovistus

Je viens de tester à l'instant sur Ubuntu 17.04 en ouvrant le fichier GLSL avec Geany et en changeant le pixel shader en live et ça marche nickel. Vraiment merci pour cette fonctionnalité super utile. Enorme !