lundi 10 novembre 2014

Nuke Tuto Blink Script, la base.


    Passons a notre premier BlinkScript!

Intro du tuto : http://unblogdecolin.blogspot.fr/2014/11/tuto-blinkscript-intro.html

A travers c'est différents articles nous allons pas innover dans le processing d'image au contraire nous allons voir des choses qui existent déjà mais qui vont nous permettre d'apprendre les bases du BlinKScript pour pouvoir plus tard se prendre la tête sur des nouveaux effets ...

    Pour ce premier BlinkScript nous allons simplement additionner les pixels a une valeurs quelconque. Nous verrons la structure de base, les inputs / outputs et la fonction process().
Nous commençons par créer un nouveau node BlinkScript et nous supprimons l’intégralité du code déjà présent dans l’éditeur de texte.

    Première chose a faire c'est de créer un objet kernel dans le quel nous allons mettre toutes nos instructions. Cet objet dérive de ImageComputationKernel qui possède deux manières de traiter les pixels : eComponentWise et ePixelWise. Pour ce premier BlinkScript nous allons utiliser eComponentWise.
Pour le moment nous avons ça :


    eComponentWise traite tout les channels d'un seul coup. C'est certainement plus performant mais nous ne pourrons pas faire d’opérations sur un channel en particulier. eComponentWise est parfaitement adapte pour notre premier BlinkScript qui est une simple addition.

    Maintenant que nous avons notre kernel, il faut que nous définissions une entrée et une sortie a l’intérieur. Image et ses différents argument sont la pour ça. Le premier argument définit si l'Image est en lecture : eRead ou en écriture : eWrite. Le deuxième définit le type d’accès au pixel, dans notre cas nous avons besoin d'eAccessPoint qui est la manière la plus simple d’accéder aux pixels nous comprendrons pourquoi dans la suite. Il existe trois autres manières d’accéder aux pixels que nous verrons dans des futurs articles. Il reste un dernier argument qui permet la gestion des bords de nos images : eEdgeClamped permet de répéter a l’extérieure de l'image la valeur du pixel le plus proche du bord, eEdgeConstant va répéter des valeurs de pixel noir 0.0 alors que  eEdgeNone  répète rien et est donc l'option la plus performante. Dans notre BlinkScript Additionator nous avons pas besoin de répéter les bords donc on va utiliser eEdgeNone.
Si nous précisons pas d'argument a notre Image les valeurs par default sont eRead, eAccesPoint et eEdgeNone.
Donc nous allons creer une entree src et une sortie dst, c'est les noms choisis par foundry mais nous pouvons les nommer comme bon nous semble.


    Il nous reste plus qu'a dériver une fonction pour que notre BlinkScript soit opérationnel c'est la fonction process() cette fonction va répéter les instructions, présentes dans son bloc, pixel après pixel et ligne après ligne. Le sens de processing des BlinkScript est toujours d'en bas a droite a en haut a gauche.
Nous créons la fonction void process(){ } a la suite de nos Image :


Dans le bloc de la fonction process() nous allons rentrer toutes nos instructions. Dans notre cas tout tiens en une ligne, j'assigne la valeur du pixel de src + une 0.5 au pixel de dst. En eComponentWise pour avoir le pixel de notre src il faut appeler la fonction src() simplement et de même pour avoir le pixel de notre dst nous appelons dst().
Notre instructions sera :


Nous compilons notre BlinkScript en cliquant sur Recompile, nous connectons une image a notre input src, un viewer sur notre BlinkScript  et nous pouvons voir toute notre image être additionne a 0.5, whouaa!.

    Nous le répétons ce BlinkScript ne fait absolument rien de fou mais c'est la meilleur façon de voir comment fonctionne un BlinkScript. En resume, pour que notre BlinkScript fonctionne il lui faut une entre et une sortie et une instruction dans process(). Il faut voir la fonction process() en peu comme une double boucle for :

for(y=0; y‹h; y++){
  for(x=0; x‹w; x++){
    ...
  }
}

Elle va parcourir tout les pixels de l'image et appliquer ses instructions sur chacun d'eux.

    Concrètement pour que notre BlinkScript soit facile utiliser il lui manque un knob pour que l'utilisateur puisse changer la valeur a additionner de manière interactive et non en changent le code. Nous verrons comment procéder dans un prochain article.

a++


C.


Nuke Tuto Blink Script, intro.







English version, here.


     Depuis la version 8 de nuke the foundry nous propose une nouveauté qui est le node de BlinkScript.
 Le node de BlinkScript a comme fonction de "processer" les pixels d'une image, c'est a dire permettre d'appliquer des calculs et des algorithmes sur chaque pixel d'une image a l'aide d'un langage de programmation. Avant l'existence du BlinkScript ce genre de calcul au niveau du pixel était possible, sans passer par le NDK, avec l'utilisation de la fonction sample() en python mais c'était extrêmement couteux en performance. Parcourir une image pixel par pixel en pyhon peut prendre plusieurs dizaines de seconds voir minutes selon l'utilisation des valeurs du pixel et de la taille de l'image. Grâce au BlinkScript les performances sont bien meilleurs.

    Nous allons rapidement voir comment le BlinkScript fonctionne, il possède un éditeur de texte qui lui permet de recevoir le code qui lui fournit les instructions a exécuter. Une fois ce code rentré nous allons demande au BlinkScript de le convertir et de le compiler en cliquant sur le bouton Recompile ainsi il devient utilisable par nuke. Le langage utilisé pour "coder" des BlinkScript est un langage dit "kernel" avec une syntaxe proche de celle du C++ il sera converti dans un langage adapté a l’exécution de ces instructions soit sur le CPU soit sur le GPU (SMID ou OpenCL). Une fois converti et compile le BlinkScript devient aussi performant, voir plus qu'un node classique code en C++ avec le NDK. Le système de Blink a été aussi intégré aux NDK pour pouvoir développer des nodes C++ et profiter de cette nouvelle technologie CPU / GPU.

    Le réel avantage du BlinkScript est donc sa performance mais il possède quelques mauvais points. Il est bon de les savoir pour comprendre les limites de ce node et ne pas perde de temps a essayer de programmer des choses que le BlinkScript ne pourra pas faire.
    Le BlinkScript travail que sur le pixel, il est impossible de travailler sur un autre contexte. Par exemple ce n'est pas possible de paramétrer la taille d'une image, de changer de frame, de changer les connections du BlinkScript ... Il n'agit que sur le pixel.
    Le BlinkScript peut posséder des Knobs mais leurs valeurs peuvent être attribué qu'a la première exécution du BlinkScript. Au final nous pouvons qu'initialiser les valeurs des Knobs. Il est impossible de changer une valeur d'un knob en cour de processing (calcule de l'image) par contre elles peuvent être lues. Si la valeur d'un knob est changé "manuellement" le processing sera relancé automatiquement avec cette nouvelle valeur.
    Le BlinkScript étant assez nouveau la gestion des erreurs de syntaxe ou de compilation sont souvent flous et nous aide pas beaucoup pour trouver d’où vient notre erreur. Il faut se préparer a passer du temps a debugger notre BlinkScript. Une bonne connaissance en C++ peut être un avantage pour corriger et éviter ce genre d'erreurs.
    Le BlinkScript ne travail que sur les channels R, G, B, et A ce qui nous oblige très souvent a faire précéder le BlinkScript d'un Shuffle pour rediriger les Channels souhaité vers RGBA.
    Nous pouvons en déduire que le BlinkScript est a utiliser principalement dans un gizmo entouré d'une panoplie de nodes pour le préparer et agir sur d'autre contexte que celui du pixel.

   Une fois satisfait du code de votre BlinkScript il est possible de le publier, c'est a dire que nuke va préparer le node a une utilisation en production. Nuke va grouper notre BlinkScript et linker ses knobs sur l'interface du group. Nous avons le choix de crypter le code source pour éviter tout plagia si notre souhait est de garder secret nos supers algorithmes, l’éditeur de texte disparaitra. Si nous décidons de ne pas crypter, le code source sera accessible dans l’éditeur de texte du BlinkScript.

    Voila nous avons fait un rapide tour d'horizon de ce nouveaux node. Son fonctionnement, ses avantages et ses désavantages nous paraissent plus clair. Nous sommes prés a nous lancer dans le développement d'un BlinkScript. Dans les prochains articles nous allons voir comment utiliser les différentes fonctions du BlinkScript a travers plusieurs exemples.

Suite du tuto :  http://unblogdecolin.blogspot.fr/2014/11/nuke-tuto-blink-script-suite.html

A++

C.



    Since version 8 of nuke the foundry proposes a novelty that is the node of BlinkScript.
    The node of BlinkScript as function to process the pixels of an image, that is possible to apply calculations and algorithms on each pixel of an image using a programming language. Before its existence such of calculation at the pixel level was possible, without going through the NDK, with the use of the sample() function in python but it was extremely costly in performance. Browsing image pixel a pixel with pyhon may take severals tens of seconds depending using of pixel values and the image size. Thanks to BlinkScript performance is much better.

    Quickly we'll see how the BlinkScript works, it has a text editor that allows it to receive the code which provides instructions to execute. Once the code has been entered we will ask the BlinkScript to convert and compile it by clicking the button Recompile, so it becomes usable by nuke. The language used to "encode" the BlinkScript is a sort of language called "kernel" with a syntax similar to the C++ then it will be converted into a suitable language to the execution of these instructions either on the CPU or on the GPU (MISA or OpenCL ). Once converted and compiled BlinkScript also becomes effective, like a classic node code in C ++ with the NDK. Blink system has also been integrated into the NDK to develop nodes in C ++ and enjoy this new CPU / GPU technology.

    The real advantage is BlinkScript's performance but it has some bad points. It is good to know to understand the limits of this node and not wast our time trying to manage things that BlinkScript can not do.
   The BlinkScript work on the pixel, it is impossible to work on a different context. For example it is not possible to set the size of an image, change frame, change the connections BlinkScript ... It works only on the pixel.
    The BlinkScript may possess Knobs but their values can only be assigned has the first run of the BlinkScript. Finally, we can just initializes the values of the Knobs. It is impossible to change a value of a knob during processing, in contrast they can be read. If the value of a knob is changed "manually" the processing will be restarted automatically with this new value.
    The BlinkScript being fairly new that's why error handling syntax or compilation are often vague and not much help us to find where our error is. We must prepare to spend our time to debug BlinkScript. A good knowledge of C ++ can be a benefit to correct and prevent such errors.  
    The BlinkScript work on the channels R, G, B, A and so we have very often precede the BlinkScript a Shuffle to redirect to the desired RGBA Channels.
     We can deduce that the BlinkScript is to use primarily in a gizmo surrounded by an array of nodes to prepare and act on context other than the pixel.


    Once satisfied with the code of your BlinkScript it is possible to publish it, that nuke will prepare the node has a production use. Nuke will group our  BlinkScript and link knobs to its interface group. We have the choice to encrypt the source code to avoid plagiarism if our desire is to keep our secret algorithms, the text editor will disappear. If we decide not to encrypt the source code will be available in the text editor BlinkScript.

    Here we did a quick tour of this new node. Its operation, its advantages and disadvantages we seem clearer. We are ready to get into the development of a BlinkScript. In future articles we will see how to use the various functions of BlinkScript through several examples.

The next tuto :    http://unblogdecolin.blogspot.fr/2014/11/nuke-tuto-blink-script-suite.html

A++

C.









jeudi 9 janvier 2014

Ajouter des Widget dans des QListWidget et les appeler


    Voila une petite maniere de creer des widgets dans les lignes dune QListWidget et de pouvoir les appeler pour les utiliser.



from PySide.QtGui import *
from PySide.QtCore import *

class Win(QListWidget) : 
    def __init__(self) : 
        super(Win, self).__init__()

        s = QSize(25, 25)

#On met des widget type QCheckBox dans nos ligne
#de notre QListWidget

    #on rajoute 10 ligne
        for i in range(10) : 

        #On instancie un QListWidgetItem qui contiendra 
        #nos QCheckBox et QSpinBox
            item = QListWidgetItem()
            item.setSizeHint(s)

        #on cree nos widgets
            if i % 2 == 0 :
                cb = QCheckBox("Check Box " + str(i))
                cb.setFixedHeight ( 25) 
            else : 
                cb = QSpinBox()
                cb.setSuffix(" : Spinn Box " + str(i))
                cb.setFixedHeight ( 25)

        #On ajoute notre QListWidgetItem dans une ligne
        #grace a addItem() de QListWidget
            self.addItem(item)

        #Et on ajoute nos CheckBox et SpinBox a nos QListWidgetItem
        #Grace a la methode setItemWidget() de QListWidget
        #Le premier arg est le QListWidgetItem, le second arg est notre
        #Widget, pour nous QCheckBox et QSpinBox
            self.setItemWidget(item, cb)


            self.show()

#On recupere nos widget spinbox et checkbox : 

    #liste tous les items present dans le QListWidget
    #dans notre cas se sont des QListWidgetItem 
        widgetItems = []
        for i in range(self.count()) : 
            item = self.item(i)
            widgetItems.append(item)

    #on liste tous nos widget present dans nos QListWidgetItem
    #en passant par la method itemWidget() de QListWidget()
        checkItems = []
        for it in widgetItems : 
            ch = self.itemWidget(it)
            checkItems.append(ch.text())

            
s = Win()

mercredi 8 janvier 2014

Gizmo Nuke Time Code

    Et voila j'ai enfin fais un node de timecode pour nuke.
Vous pouvez le copier/coller dans votre graph nuke ou en faire un fichier .gizmo :

Gizmo {
 name TimeCode tile_color 0xff addUserKnob {20 "" l Color}
 addUserKnob {41 ramp T Text1.ramp}
 addUserKnob {41 color T Text1.color}
 addUserKnob {41 p1 l "point 1" T Text1.p1}
 addUserKnob {41 color0 l "color 0" T Text1.color0}
 addUserKnob {41 p0 l "point 0" T Text1.p0}
 addUserKnob {20 "" l Node}
 addUserKnob {41 output T Text1.output}
 addUserKnob {41 premult T Text1.premult}
 addUserKnob {41 cliptype l "clip to" T Text1.cliptype}
 addUserKnob {41 replace T Text1.replace}
 addUserKnob {41 invert T Text1.invert}
 addUserKnob {41 opacity T Text1.opacity}
 addUserKnob {26 "" l mask}
 addUserKnob {41 maskChannelMask l "" -STARTLINE T Text1.maskChannelMask}
 addUserKnob {41 maskChannelInput l "" -STARTLINE T Text1.maskChannelInput}
 addUserKnob {41 inject T Text1.inject}
 addUserKnob {41 invert_mask l invert T Text1.invert_mask}
 addUserKnob {26 ""}
 addUserKnob {20 Font n 1}
 Font 0
 addUserKnob {41 font T Text1.font}
 addUserKnob {41 index l "" -STARTLINE T Text1.index}
 addUserKnob {41 size T Text1.size}
 addUserKnob {41 kerning T Text1.kerning}
 addUserKnob {41 leading T Text1.leading}
 addUserKnob {41 xjustify l justify T Text1.xjustify}
 addUserKnob {41 yjustify l "" -STARTLINE T Text1.yjustify}
 addUserKnob {20 "" n -1}
 addUserKnob {20 Transform n 2}
 addUserKnob {41 box T Text1.box}
 addUserKnob {41 matrix T Text1.matrix}
 addUserKnob {41 translate T Text1.translate}
 addUserKnob {41 rotate T Text1.rotate}
 addUserKnob {41 scale T Text1.scale}
 addUserKnob {41 skew T Text1.skew}
 addUserKnob {41 center T Text1.center}
 addUserKnob {20 "" n -1}
}
 Input {
  inputs 0
  name Input1
  xpos 177
  ypos -144
 }
 Text {
  message "\n\[python str(int(nuke.thisNode().knob('hour').value())).zfill(2)]:\[python str(int(nuke.thisNode().knob('min').value())).zfill(2)]:\[python str(int(nuke.thisNode().knob('sec').value())).zfill(2)]:\[python str(int(nuke.thisNode().knob('frame').value())).zfill(2)]\n\n\n"
  font C:/Windows/Fonts/arial.ttf
  size 80
  kerning 0.1
  yjustify center
  box {512 389 1536 1167}
  translate {154 84}
  center {1024 778}
  name Text1
  selected true
  xpos 185
  ypos -71
  addUserKnob {20 User}
  addUserKnob {7 frame}
  frame {{"\[python -execlocal \\nret\\ =\\ \\ nuke.frame()\\ %\\ nuke.Root().fps()]"}}
  addUserKnob {7 sec}
  sec {{"\[python -execlocal \\ns\\ =\\ nuke.frame()\\ //\\ nuke.Root().fps()\\ %\\ 60\\ \\nret\\ =\\ s\\n\\n]"}}
  addUserKnob {7 min}
  min {{"\[python -execlocal s\\ =\\ nuke.frame()\\ //\\ nuke.Root().fps()\\nret\\ =\\ s\\ //\\ 60\\ %\\ 60]"}}
  addUserKnob {7 hour}
  hour {{"\[python -execlocal s\\ =\\ nuke.frame()\\ //\\ nuke.Root().fps()\\nret\\ =\\ s\\ //\\ 3600\\n]"}}
  addUserKnob {41 message_1 l message T Text1.message}
 }
 Output {
  name Output1
  xpos 177
  ypos -4
 }
end_group



mardi 29 octobre 2013

NUKE list all callbacks

   Hey,
It's been a long time i searched how to list all callbacks present in a nuke script...
And now i get it !

We can list them by type like knobChanged or onCreate and so on.

We acces by the callbacks module in .nuke :

 

nukeCallbacks = nuke.callbacks


And then use its variables by the type :

 

nukeCallbacks = nuke.callbacks
allKnobChanged = nukeCallbacks.knobChangeds



Nuke list callbacks in a big dictionary with the node Class as key and its value as a list who contains the function to call and its arguments.
 

nukeCallbacks = nuke.callbacks
allKnobChanged = nukeCallbacks.knobChangeds

# Result: 
{'Read': [(<function readFn at 0x00000000047A3EB8>, (101,), {}, None)], 'Write': [(<function writeFn at 0x00000000047A3D68>, (), {}, None)], '*': [(<function readFn at 0x00000000047A3EB8>, (101,), {}, 'Read1')], 'Roto': [(<function rotoFn at 0x00000000047A3DD8>, (), {}, None)]}

Here some types examples :


 
autolabels = {}
beforeFrameRenders = {}
beforeRenders = {}
filenameFilters = {}
knobChangeds = {}
onCreates = {}
onDestroys = {}
onScriptCloses = {}
onScriptLoads = {}
onScriptSaves = {}
onUserCreates = {}
updateUIs = {}

lundi 22 juillet 2013

PyQt QGraphicsView la base pour un node graph

    Ici je vais vous présenter une base pour faire un "node graph" ou viewport 2D... mon exemple est très simple il y a seulement deux éllipses en guise de "nodes",pour l'instant on regarde juste le paramétrage de base de notre QGraphicsView qui est notre support de base, peut être un jour je vous représenterai un ticket pour les nodes et leurs connections.


Un QGraphicsView avec une grille, deux items sélectionnable et bougeable, un lasso de sélection et un alt-drag pour bouger dans la vue.


 
from PyQt4 import QtGui, QtCore


class View(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)
        self.resize(500, 500)

#on place le point de pivot des transformation au niveau du pointeur
       self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
       self.setResizeAnchor(QtGui.QGraphicsView.AnchorViewCenter)
#on cache les scrollBar
       self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
       self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)  
        
#active l’antialiasing
        self.setRenderHint(QtGui.QPainter.Antialiasing)
        
#creation du scene qui contient les items et sera dans la QView
        self.scene = QtGui.QGraphicsScene()
        self.scene.setSceneRect(-50000, -50000, 100000, 100000)

        
#Ajout d'une grille en fond
        self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(60,60,60), QtCore.Qt.CrossPattern))
  
#creation de deux elipse simple a la scene, selectable et movable
        ep = self.scene.addEllipse (20, 40, 50, 50)
        ep.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        ep.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
 
        epS = self.scene.addEllipse (20, 120, 50, 50)
        epS.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        epS.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
        
#parametrage du drag mode  rubber …. permet davoir un lasso rectangulaire de selection
        self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
        self.setRubberBandSelectionMode(QtCore.Qt.IntersectsItemShape)
        self.setScene(self.scene)
        
        
#alt drag scroll bar, permet de se deplacer dans le graph grace a la touche alt.       
    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Alt:
            self.setDragMode(QtGui.QGraphicsView.ScrollHandDrag)
    def keyReleaseEvent(self, event):
        if event.key() == QtCore.Qt.Key_Alt:
            self.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
            
        
d = View()
d.show()




vendredi 7 juin 2013

Displacement 32bit

   Un simple post sur la découverte d'un lien qui m'a appris, enfin!, a régler correctement une displace avec zbrush et vray. Finit le tatonage du shift ... place a la précision:

http://www.cggallery.com/tutorials/displacement/