Bonjour,
Étant donné que j'approuve particulièrement les matières procédurales, je me suis demandé s'il n'y avait pas moyen d'en créer de nouvelles... et apparemment si !
La création d'une matière en Python est abordable grâce à la classe ShaderData, voici mes premiers essais réussis :
Je souhaiterais à terme créer une matière procédurale avec une formule paramétrable.
Cependant, je bloque sur l'interface, je n'arrive pas à créer le moindre paramètre pour ma matière.
La doc à ce sujet reste relativement épurée
J'ai découvert cette page en japonais où le nippon arrive à afficher une boîte de dialogue au clique sur la matière, mais j'ai du mal à cerner son code. Quelqu'un a-t-il une idée sur la façon de créer un tableau de paramètres comme ceux des bruits procéduraux ?
Je me suis basé sur l'exemple Py-Fresnel.pyp de la doc, qui peut vous servir de support.
Code PHP:
import os
import math
import c4d
from c4d import plugins, bitmaps, utils, documents
MODULE_ID=1028230
class MatFormule(plugins.ShaderData):
def __init__(self):
self.SetExceptionColor(c4d.Vector(1,0,0)) # Couleur si erreur
def formule(self, x, y, z, i):
n = c4d.utils.noise.Noise(c4d.Vector(x, y, z), i)*10
f = math.cos(x+n)
return f
def Output(self, sh, cd):
if cd.vd: # 3d
vec = cd.vd.p * 0.1
v = self.formule(vec.x, vec.y, vec.z, 10)
vec.x = v
vec.y = v
vec.z = v
vec = abs(vec)
return vec
else: # 2d
return c4d.Vector(0.0)
def FreeRender(self, sh):
# Libère la mémoire
return
if __name__=='__main__':
plugins.RegisterShaderPlugin(MODULE_ID, "Formule", 0, MatFormule, "", 0)
Dernière modification par César Vonc ; 19/02/2012 à 18h18.
Salut,
Je dis rien à chaque fois et je suis en silence mais là c'est trop : t'es un fou furieux du langage Python :
Hyper balise et balaise comme mec! chapeau bas.
Yaya. °) Merci pour tout ce que tu fais.
Dernière modification par yayaprod ; 10/02/2012 à 22h24.
Les détails font la perfection, et la perfection n'est pas un détail.http://yayaprodtm.cgsociety.org/
LdV.
Woow Cesar, je suis ébloui par tes compétences et ta curiosité. Ca ouvre de belles perspectives quand je vois tes premiers résultats. Je m'installe au chaud pour suivre ca de plus près
kenavo !! // Pinterest KAMIGAZ®
Pour les données perso dans les interfaces, (et de manière globale) il faut que tu regardes du coté des fichiers de ressources.
(dialog ressources)
Passer par les fichiers ressources ça facilite les mises à jour et les portage multi-langues.
Une piste à suivre (j'ai recrée l'arbo de ton plugin). Mais la fonction pour récupérer la valeur de la donnée n'est clairement pas à la bonne place, elle crée des refresh ce qui ralenti complètement le processus :p
en gros, il faut créer dans le répertoire description les interfaces pour les outils, les shaders, les objets. Pour les fenêtres d'interface tu vas mettre ton fichier dans le répertoire dialogs. (idem pour le répertoire string_fr)
Lorsque tu enregistres ton plugin, tu peux mettre un nom de ressource. Il doit correspondre au nom du fichier sans le .res
Tu as deux fichiers, le .h pour la déclaration des ID et le .res pour l'interface elle même.
Tu peux créer ces fichiers assez facilement avec resEdit (dispo chez maxon).
Sinon faut ouvrir les fichiers déjà existant dans le répertoire ressources de c4d et regarder ^^
Dans la doc c++ faut regarder à dialog Ressources, y a pas mal d'info.
edit : le coup classique d'oublier de lier le fichier.
formule.zip
Wouahou ! Ton image est superbe ! cette matière est vraiment incroyable…et bravo pour tes recherches sur python
http://dr-graphix.blogspot.com/-DRG Design / Portfolio
Ça ressemble aux shaders de StrataVision en 1847.
Je suis quand même épaté par tes recherches tous azimuts et tes capacités à développer, chapeau bas !
÷ R19 Studio ÷ cacahuètes ÷
ça y'est, on vient de basculer dans l'ère où c'est moi qui vais te demander des conseils en programmation.
Il me semble que tu as vraiment attrapé le virus, en tout cas bravo c'est vraiment du beau boulot
Dernière modification par oli_d ; 11/02/2012 à 20h39.
Merci. Je ne suis pas prêt de te détrôner, Oli_d !
J'ai encore beaucoup de mal pour l'interface, j'ai mes trois fichiers :
matformule.h :
matformule.res :Code PHP:
#ifndef _matformule_H_
#define _matformule_H_
enum
{
MATFORMULE_SOURCE = 1000,
MATFORMULE_COUL = 1001
};
#endif
matformule.str :Code PHP:
CONTAINER matformule
{
INCLUDE Mpreview;
INCLUDE Xbase;
GROUP ID_SHADERPROPERTIES
{
LONG MATFORMULE_SOURCE { MIN -100000; MAX 100000; }
COLORFIELD MATFORMULE_COUL { }
}
}
Mais j'ai inévitablement une erreur dans matformule.res à la ligne 9, à cause de mon COLORFIELD ; pourtant c'est ce qu'ils font dans la doc, je pige pas (tout baigne si je remplace COLORFIELD par REAL, sinon).Code PHP:
STRINGTABLE matformule
{
MATFORMULE_SOURCE "Source";
MATFORMULE_COUL "Couleur";
}
Les
INCLUDE Mpreview;
INCLUDE Xbase;
inluent quoi, exactement ? Peut-être qu'il m'en manque un pour mon champ couleur.
Édition : Petite mise à jour de l'interface avec l'ajout du contraste et de l'aperçu :
Dernière modification par César Vonc ; 12/02/2012 à 00h18.
dans le fichier oLight.res (l'interface d'une lumière de base) pour la couleur ils ont utilisé COLOR LIGHT_COLOR { OPEN; PARENTCOLLAPSE; }
C'est peut être ça qu'il faut prendre, le colorfield étant peut être réservé à une boite de dialogue.
Pour les includes,ça correspond aux informations déjà crée et commune à tous les objets ou textures par exemple.
INCLUDE Obase;
vas rajouter dans ton interface l'onglet "base" d'un objet, avec tous les champs qu'il contient habituellement.
Pour une texture, Xbase et Mpreview, ça doit rajouter l'onglet base d'une texture et la préview matière.
Une fois de plus, j'ai pas spécialement trouvé beaucoup d'info à ce sujet, j'ai tendance à aller voir dans les fichier .res de c4d pour voir comment ils ont fait ^^
En effet, COLOR marche parfaitement, merci !
J'ai regardé d'autres .res et ai découvert
Pour implémenter une zone de texte Python, que je récupère, compile() puis exécute avec exec().Code:STRING MATFORMULE_CODE { CUSTOMGUI MULTISTRING; PYTHON; SCALE_V; }
Tout semble bien fonctionner, encore quelques petits réglages et le module sera bientôt prêt. Voici à quoi il ressemble actuellement :
Je créerai un sujet bien propre et fournirai quelques codes d'exemple, je pense que les matheux pourront s'en donner à cœur joie !
Dernière modification par César Vonc ; 12/02/2012 à 23h30.
et t'as fais comment pour activer le preview du shader ? que j'évites de chercher ^^'
non ben j'ai rien dit ça marche maintenant -_-'
Dernière modification par valkaari ; 13/02/2012 à 00h00.
En fait c'est la même sortie que pour l'affichage 3d, sauf que objet de l'aperçu n'a pas de paramètre vd (VolumeData), donc on récupère les coordonnées des points UVW au lieu de XYZ :
Le retour étant la couleur RVB pour chaque pixel rendu.Code PHP:
def Output(self, sh, cd):
if cd.vd: # vue 3d
# Points XYZ rendus de l'objet : cd.vd.p
return c4d.Vector(0, 0, 0)
else: # vue 2d et aperçu
# Points UVW rendus de la texture de l'objet : cd.p
return c4d.Vector(0, 0, 0)
Ceci dit l'aperçu peut afficher un objet 3d au lieu d'un plan (clic droit dessus).
Je posterai bientôt le code en entier !
si tu aimes les textures procédurales, je te recommande ce bouquin En tout cas, c'est super !
Le rendu, c'est juste de l'intégration numérique sur un espââââââce de dimension infinie...trivial quoi
Ah dommage que ce livre ne soit pas en français, tarlack, il a pourtant l'air intéressant.
Voici donc la première version bêta, avec un fichier d'exemple.
Le dossier matformule est à placer dans le dossier plugin de c4d.
J'ai remarqué que vous étiez plus attentifs avec des images. ^^
Le code perso s'ajoute automatiquement là où se trouve exec self.code, au sein même de la fonction Output(), donc toutes les variables de cette fonction sont utilisables dans votre code (si vous utiliser cd.vd , vérifiez impérativement qu'il existe).Code PHP:
import os
import math
import c4d
from c4d import plugins, Vector
from c4d.utils.noise import Noise
from math import *
MODULE_ID = 1028230
class MatFormule(plugins.ShaderData):
tps = 0
ech = 0.1
echxyz = Vector(1, 1, 1)
contra = 0
lumi = 0
cola = Vector(0, 0, 0)
colb = Vector(1, 1, 1)
colc = Vector(1, 0, 0)
codetxt = 'n = Noise(Vector(x, y, z), (t+cos(x)+cos(y)+cos(z))*10)\nr = v = b = n'
code = compile(codetxt, '<string>', 'exec')
mode = 1
def Init(self, node):
donnees = node.GetDataInstance()
donnees.SetReal(1000, self.tps)
donnees.SetReal(1001, self.ech)
donnees.SetVector(1003, self.echxyz)
donnees.SetReal(1002, self.contra)
donnees.SetReal(1006, self.lumi)
donnees.SetVector(1004, self.cola)
donnees.SetVector(1005, self.colb)
donnees.SetString(1007, self.codetxt)
donnees.SetVector(1008, self.colc)
donnees.SetLong(1010, self.mode)
return True
def recup(self, sh):
donnees = sh.GetDataInstance()
self.tps = donnees.GetReal(1000)
self.ech = donnees.GetReal(1001)
self.echxyz = donnees.GetVector(1003)
self.contra = donnees.GetReal(1002)
self.lumi = donnees.GetReal(1006)
self.cola = donnees.GetVector(1004)
self.colb = donnees.GetVector(1005)
txt = donnees.GetString(1007)
self.colc = donnees.GetVector(1008)
self.SetExceptionColor(self.colc)
self.codetxt = txt
self.code = compile(txt, '<string>', 'exec')
self.mode = donnees.GetLong(1010)
def InitRender(self, sh, irs):
self.recup(sh)
return 0
def Output(self, sh, cd):
if cd.vd and self.mode is 1: # 3d
vec = cd.vd.p * self.ech
else: # 2d et aperçu
if self.mode is 0:
vec = (cd.p) * 100 * self.ech # Coordonnées UVW
else:
vec = (cd.p-0.5) * 100 * self.ech # Coordonnées UVW
x = vec.x * self.echxyz.x
y = vec.y * self.echxyz.y
z = vec.z * self.echxyz.z
tu = cd.p.x
tv = cd.p.y
tw = cd.p.z
t = self.tps
r = v = b = 0
exec self.code
vec = Vector(r, v, b)
dif = self.colb - self.cola
vec.x = dif.x * vec.x + self.cola.x
vec.y = dif.y * vec.y + self.cola.y
vec.z = dif.z * vec.z + self.cola.z
vec = ((vec-0.5) * (self.contra + 1)) + 0.5 + self.lumi
return vec
def FreeRender(self, sh): # Libère la mémoire
return
if __name__=='__main__':
plugins.RegisterShaderPlugin(MODULE_ID, "Formule", 0, MatFormule, "matformule", 0)
Dernière modification par César Vonc ; 13/02/2012 à 19h13.
pfiou c'est juste épique comme thread ! Merci César, tes procédurales sont à tomber !
kenavo !! // Pinterest KAMIGAZ®
respect
En plus de ton plugin et de ton code, la matière procédurale pour le ciel est à tomber, merci pour le partage.
Je pense qu'il y a quand même moyen de faire plus simple, pour le ciel.N'oubliez pas de renommer les matériaux, hein ! :-Pexemple mis à jour, ni vu ni connu.
Dernière modification par César Vonc ; 14/02/2012 à 23h24.
Bravo, tu progresses super vite ^^
T'as le droit aux codes correspondant aux caractères latin.
Ce qui donne "Luminosit\u00E8" dans le fichier .strCode:é è ç à ê ë \u00E9 \u00E8 \u00E7 \u00E0 \u00EA \u00EB
Ah d'accord, je me disais aussi, le fichier str ne marche qu'en ANSI et non en unicode.
J'ai ajouté deux petites cases à cocher pour limiter ou non la valeur minimale maximale de la couleur. Car j'ai remarqué qu'un noir avec une valeur négative pouvait illuminer du noir dans le canal luminescence !
De la même manière, un blanc avec une valeur supérieure à 1 placée dans le canal couleur équivaut à sa couleur -1 dans le canal luminescence.
De cette manière, on évite d'avoir des surprises.
Je bloque en revanche pour récupérer les coordonnées de l'objet en cours de rendu, pour pouvoir proposer d'autres espaces que Monde et UV, car en Monde, les valeurs x y z sont absolues, or j'aimerais récupérer les relatives.
Quelque chose me dit que c'est dans c4d.modules.render.BaseVolumeData, mais je n'arrive pas à trouver où.
Dernière modification par César Vonc ; 15/02/2012 à 14h55.
Trés intéressant tes recherches sur les procedurals césar, bravo bravo
Oops, je m'installe si cela ne te dérange pas.
Bien à toi
Merci bien, je garderai ce sujet pour le développement. La première version est disponible !
http://frenchcinema4d.fr/showthread....i%E8re-Formule
Terrible tous ça
Merci !