Übung 1 - Blender Setup & Scripting-Tools

Einführung

Digitale Medienproduktionen

Die meisten Prozesse in digitalen Medienproduktionen werden mit Hilfe hochspezialisierter Softwaretools durchgeführt. 3D-Modelle und Animationen, Post-Produktion, Color-Grading, Greenscreen Keying, Camera-Tracking usw. sind nur effizient mit Hilfe speziell dafür entwickelter Softwarepakete in Produktionen einsetzbar.

Ohne jeglichen Anspruch auf Vollständigkeit hier ein paar Beispiele häufig zum Einsatz kommender Werkzeuge:

  • Maya
  • Cinema 4D
  • Houdini
  • 3ds Max
  • Nuke
  • Blender
  • After Effects
  • DaVinci Resolve

Effizienz bei Bewegtbild-Produktionen

Speziell bei Bewegtbild-Medien genügt aber oft nicht die manuelle Bedienung dieser Werkzeuge. Da hier zwischen 24 und 60 Bilder pro Sekunde, bei Stereoproduktionen sogar doppelt so viele, bearbeitet oder generiert werden müssen, ist eine manueller Bild-für-Bild Prozess zu ineffizient.

Eine ausreichende Effizienz lässt sich hier meistens nur mit Hilfe von automatisierten, selbst ablaufenden Prozessen erzielen - also möglichst ohne viel zeitaufwändige und kostenintensive menschliche Interaktion.

Automatisierung durch Skripting

Derartige automatisierte Prozesse lassen sich meist nur mit Hilfe von Algorithmen, also durch Programmierung, realisieren. Alle oben genannten Beispiele bieten hierzu eine Programmierschnittstelle an, mit der sich meist sämtliche Funktionen der Software per Code ansprechen lassen. Oftmals ist bereits in die Software ein Code-Editor eingebaut. Damit ist die Programmierung so genannter Skripte oder Makros möglich.

Die Rolle von Python in der Medienproduktion

In vielen Software-Paketen, die in Medienproduktionen zum Einsatz kommen, wird die Programmiersprache Python verwendet - so können zum Beispiel alle oben genannten Produkte durch Python-Skripte automatisiert werden.

In dieser Veranstaltung soll daher die Verwendung von Python im Umfeld von Medienproduktionen gelehrt werden. Nach einer allgemeinen Einführung in die Programmiersprache wird schnell die Verwendung von Python in der 3D- und Compositing/VFX-Software Blender erarbeitet. Blender wird dazu mit einer eigenen Python-Distribution ausgeliefert und installiert (diese liegt im Blender-Installationsverzeichnis in einem eigenen python Unterverzeichnis). Obwohl der Kern von Blender selbst in den Programmiersprachen C und C++ geschrieben wurde, ist der gesamte Source-Code eng mit Python verzahnt. Nahezu jede Funktionalität, die sich in Blender über das User Interface auslösen lässt, kann auch mit Python-Befehlen aus einem Skript aufgerufen werden. Darüber hinaus ist auf sämtliche Daten innerhalb von Blender über Python-Strukturen zugreifbar. Dazu zählen u.a.

  • Szenen und Objekte
  • Geometrie
  • Kamera und Beleuchtung
  • Materialien
  • Texturen

Erste Schritte

In dieser Übung wollen wir uns mit dem Setup von Blender für Scripting, sowie den Tools, die uns von Blender selbst dafür zur Verfügung gestellt werden beschäftigen.

Ladet euch zunächst von Blender.org die aktuelle Version von Blender herunter.
  • Dieses Script behandelt die Version 2.91 / 2.92. Zukünftige Versionen könnten eventuell Änderungen an der API vornehmen, normalerweise bleibt die API bei Updates jedoch großteils unverändert.
  • Öffnet Blender und in Blender die Preferences Preferences
  • Aktiviert hier nun im Interface Tab Python Tooltips und Development Extras

Python Tooltips zeigt nun beim Hovern mit dem Cursor über einen Wert dessen Pfad in der Blender API an.
Python Tooltip
Development Extras Ermöglicht einige Funktionen, die uns das Scripten erleichter, wie z.b. das Anzeigen des Python-Codes von Features (RMBEdit Source). Der Sourcecode wird dann im Texteditor geöffnet. Da manche Bereiche der UI automatisch über den C-Kern von Blender generiert werden, gibt es jedoch nicht zu jedem Wert und Knopf ein Pythonscript.
Edit Source

Scripting Tools

Wechselt nun zum Workspace-Tab Scripting
Scripting Workspace

  • Der 3D View 1 stellt die aktuelle Szene in 3D dar.
  • Mit der Python Konsole 2 kann wie mit dem python-Befehl von der Kommandozeile des Betriebssystems interaktiv Python-Code Zeile für Zeile eingegeben werden.
  • Das Info Fenster 3 gibt den Code von in Blender ausgeführten Aktionen aus
  • Im Text Editor 4 wird der Code für unsere Scripte geschrieben
  • Die beiden Outliner Fenster 5 zeigen oben die aktuelle Szenen-Hierarchie und unten alle Daten des geöffneten Blender Files
  • Der Properties Editor 6 ermöglicht die Bearbeitung von Werten des aktuellen Objekts, sowie Einstellungen der Szene.

Ein weiteres wichtiges Werkzeug ist die Systemkonsole.

  • Wenn Windows benutzt wird, wählt Window → Toggle System Console

  • In Linux und Mac muss Blender über das Terminal gestartet werden und dieses Terminal erfüllt dann deren Zweck: bpy.types.VIEW3D_MT_add.remove(add_object_button)

    • Linux: Wenn Blender über die Packetverwaltung installiert wurde (was übrigens nicht empfehlenswert ist, da diese Versionen meist veraltet sind, keinen CUDA support haben etc.) einfach in die Konsole blender eingeben. Wenn Blender von der Webseite heruntergeladen und extrahiert wurde, muss der ganze Pfad zur Blender executable angegeben werden - z.b. /home/software/blender-2.91.2-linux64/blender

    • MacOS: Im Terminal den Pfad zur Blender installation angeben - z.b. "/Applications/Blender/blender.app/Contents/MacOS/blender Scripting Workspace

Nach dem Start von Blender zeigt uns die Systemkonsole die mitgelieferte Python-Installation an. Hier werden auch Fehlermeldungen und Ausgaben des print() Befehls ausgegeben.

Live Scripting

Die Python Konsole ermöglicht Live Scripting. Auch Auto Vervollständigung ist möglich. So kann beispielsweise bpy. (blender python API) getippt werden und anschließend mit TAB die verfügbaren nachfolgenden Pfade angezeigt werden. Mit Pfeil nach oben kann der letzte Befehl wieder aufgerufen werden.

Mit folgendem Befehl können wir z.b. das selektierte Objekts um zwei Einheiten entlang der Y-Achse verschieben.

bpy.ops.transform.translate(value=(0, 2, 0))

Pfade können auch in Variablen gespeichert und dann über diese manipulert werden:

my_cube = bpy.context.object
my_cube.location.x += 2

wird lediglich der Pfad zu einer Variablen oa. eingegeben, gibt die Konsole deren Wert zurück. Z.b. my_cube.scale gibt Vector((1.0, 1.0, 1.0)) zurück. Wir wissen also nun, dass es sich bei scale um eine Datenstruktur “Vector” handelt und diese die Werte (1,1,1) für x, y und z hat.

Die Struktur der API wird im folgenden Kapitel noch genauer behandelt.

Was fällt uns hier ins Auge?:

  • Alles, was Blender für das Skripten zur Verfügung stellt, ist über das Python-Modul bpy abrufbar. Unterhalb von bpy gibt es eine weitere hierarchische Aufteilung, so dass Blender-Kommandos in Python folgende Struktur haben:

    bpy.abc.def.[...].command()
    

    Das Kommando bpy.ops.transform.translate() verwendet aus der Gesamtheit aller Blender-Python-Funktionalität bpy die Untergruppe der Operatoren ops, dort wird dann aus der Untergruppe der Transformations-Operatoren transform die Methode translate aufgerufen.

  • Funktionen (Methoden), die Parameter entgegen nehmen, verwenden meist named Paramter. Im Beispiel oben muss daher der Verschiebungsvektor, der an die Methode translate übergeben wird, mit value=... explizit benannt werden. Bislang haben wir bei Python-Methoden die aus anderen Programmiersprachen bekannten positional Parameter kennen gelernt, bei denen die Position in der Parameterliste eindeutig bestimmt, welcher Parameter gemeint ist.

  • Vektoren werden in einer 3D-Anwendung an allen möglichen Stellen verwendet. So auch in Blender, z.B. für die Angaben von Verschiebungen, Positionen, Normalen, Euler-Winkel, Textur-Koordinaten usw.. Diese können in Blender Python als Tupel (Siehe Lektion 2 - Datentypen) angegeben werden.

Abläufe als Script speichern

Das Info Fenster gibt uns für die meisten Aktionen, die wir in Blender tun den Python-Code aus, der im Hintergrund ausgeführt wird. So können wir schnell Arbeitsabläufe einfach aus dem Info Fenster herauskopieren und als Script abspeichern, um uns repetetive Arbeit zu sparen.

Info Fenster Das Info Fenster nachdem ein Affenkopf hinzugefügt, diesem ein Subdivisio Surface Modifier hinzugefügt und er auf der Z-Achse um 2.0 skaliert wurde

  • Der Inhalt des Info-Fensters kann mit LMB + Drag selektiert werden und mit STRG + C & STRG + V in das Textfenster kopiert werden (vorher dort oben auf New klicken).

  • Damit unser Script funktioniert muss hier noch das bpy Modul importiert werden (in der Echtzeit-Konsole geschieht dies automatisch).

  • Das Script kann mit Klick auf den Play-Button oben im Texteditor oder mit dem Shortcut ALT + P (mit Mauscursor im Texteditor) ausgeführt werden.

Automatisierung von Abläufen

Die meisten Optionen der Operatoren haben Standardwerte und können weggelassen werden, wenn sie nicht benötigt werden. Es reicht daher für diesen Zweck auf folgender Code:

import bpy
bpy.ops.mesh.primitive_monkey_add()
bpy.ops.object.modifier_add(type='SUBSURF')
bpy.ops.transform.resize(value=(2, 1, 1)) 
# (2, 1, 1) steht hierbei für 2 auf X- und 1 Y- und Z-Achse. 
# Die Default-Skalierung ist (1,1,1)
in Python können Funktionsparameter (hier z.b. der value Vektor der resize Funktion) entweder in deren Reihenfolge ohne Bezeichner, oder mit Bezeichner in beliebiger Reihenfolge aufgerufen werden. Letzeres ist zu bevorzugen wenn die Parameter nicht offensichtlich sind, um den Code gut lesbar zu halten.

Wir können unseren Code natürlich auch in eine Funktion packen und diese später im Code aufrufen.

import bpy

def add_smooth_wide_monkey(wideness):
    bpy.ops.mesh.primitive_monkey_add()
    bpy.ops.object.modifier_add(type='SUBSURF')
    bpy.ops.transform.resize(value=(wideness, 1, 1))

add_smooth_wide_monkey(2)

ACHTUNG: Anders als in den meisten kompilierten Sprachen, müssen Funktionen in Python immer schon VOR deren Aufruf definiert werden.

Bei Fehlern im Code kann uns die Systemkonsole nützlich werden. Wenn beispielsweise hier ein Schreibfehler im Variablenaufruf in Zeile 6 passiert, teilt uns das die Systemkonsole folgendermaßen mit:

blender.exe

Traceback (most recent call last):
  File "/Text", line 8, in 
  File "/Text", line 6, in add_smooth_wide_monkey
NameError: name 'wiseness' is not defined
Error: Python script failed, check the message in the system console

Da dementsprechend auch der Aufruf der kaputten Funktion nicht funktioniert, wird auch in Zeile 8 ein Fehler angezeigt.

Affentheater

Wir wollen nun das Erlernte anwenden, um eine Horde von unterschiedlich gefärbten und skalierten Affenköpfen (im Rechteck angeordnet) zu erstellen.

Affentheater

  • Erstellt im Text Editor ein neues Script
  • importiert zunächst die Blender API mit import bpy
  • Um ein Gitter zu erzeugen benötigen wir zwei verschachtelte Schleifen (Zeilen und Spalten). Solche For-Schleifen in Python sind sehr einfach mit der range funktion möglich. Wird in dieser nur eine Zahl angegeben, entspricht diese der Anzahl an ausgeführten Iterationen.
for row in range(5):
    for column in range(5):
        #...Code um Affengitter mit 5 Reihen und Spalten zu erzeugen
  • Fügt nun den Code der Operatoren, den ihr aus dem Info Fenster kopieren könnt, in die geschachtelte Schleife ein. Wir wollen mit jeder Iteration:

    • Einen Affen (Suzanne) an seinem Platz im Gitter hinzufügen
    • Den Affen rotieren, damit er hübscher guckt
    • Das Shading des Meshes auf Smooth setzen
  • Entfernt nun die nicht benötigten Parameter aus den Operatorfunktionen

Das Affengitter-Script sollte nun in etwa so aussehen:

import bpy

for row in range(5):
    for column in range(5):
        bpy.ops.mesh.primitive_monkey_add(location=(3 * row ,3 * column, 0))
        bpy.ops.transform.rotate(value=-0.6, orient_axis='X', orient_type='GLOBAL')
        bpy.ops.object.shade_smooth()

Schließlich wollen wir die Verwendung von Magic Numbers (undokumentierte Zahlen irgendwo im Code) reduzieren.

  • Dazu legen wir oben im Script die entsprechenden “Konstanten” an (speziell deklarierte Konstanten gibt es in Python nicht) und setzen sie unten im Code ein.
  • Hier importieren wir noch das random modul und verwenden deren uniform Funktion, um jedem Affen eine zufällige Größe zu geben. Diese gibt einen zufälligen Wert innerhalb der Beiden übergebenen Parameter zurück.
import bpy
import random

GRID_SPACING = 3
GRID_SIZE = 5
SIZE_MIN = 0.2
SIZE_MAX = 1.2

for row in range(GRID_SIZE):
    for column in range(GRID_SIZE):
        bpy.ops.mesh.primitive_monkey_add(location=(GRID_SPACING * row ,GRID_SPACING * column, 0))
        bpy.ops.transform.rotate(value=-0.6, orient_axis='X', orient_type='GLOBAL')
        bpy.ops.object.shade_smooth()
        
        # random size
        size_x = random.uniform(SIZE_MIN, SIZE_MAX)
        size_y = random.uniform(SIZE_MIN, SIZE_MAX)
        size_z = random.uniform(SIZE_MIN, SIZE_MAX)
        bpy.ops.transform.resize(value=(size_x, size_y, size_z))

Der Affentheater Code bis hierhin

Um die Szene vor jeder Ausführung des Scripts zu leeren, kann folgender Code an den Anfang des Scripts (unter imports) gesetzt werden.

bpy.ops.object.select_all(action='SELECT') # selektiert alle Objekte
bpy.ops.object.delete(use_global=False, confirm=False) # löscht selektierte objekte
bpy.ops.outliner.orphans_purge() # löscht überbleibende Meshdaten etc.

Farbe

Nun wollen wir jedem Kopf eine eigene Farbe geben. Mit dem Scripting von richtigen Materialien werden wir uns in einer späteren Übung auseinandersetzen. Für dieses Beispiel werden lediglich die color Variable jedes Objektes im Loop setzen, der für sich alleine stehend noch keinen Einfluss auf das Ergebnis beim Rendering hat. Im UI ist dieser Wert im Properties Editor → Object → Viewport Display zu finden.

objectcolor

Wir können ihn uns auf Objekten jedoch anzeigen lassen, indem wir im im Shading Menü → Color auf Object stellen.

viewport_objectcolor

  • Stellt wie oben gezeigt das Viewport Shading auf Object
  • Legt in der for-Schleife nun einen Wert an, der eine zufällige Farbe generiert und dem aktiven Objekt zuweist
object_color = (
    random.uniform(0, 1),
    random.uniform(0, 1),
    random.uniform(0, 1),
    1 # Alpha-Wert der Farbe (Intransparenz) - soll hier immer 1 sein
)

bpy.context.object.color = object_color

Aufgabe bis zum nächsten Mal

  • Schreibt ein Script, welches eine Horde (5 oder mehr) von Affen in der Szene platziert und im Kreis anordnet
  • Lasst die Affenköpfe alle in die Mitte der Szene gucken
  • Freiwillig: Verbessert den Farbzuweisungs-Code, um den Affen natürlichere Farben zuzuweisen. Seht euch dazu mathutils.color an.

img

  • Experimentiert auch gerne mit weiteren Funkionen

Tipps

  • Die Formel für die Position eines Punktes im Einheitskreis ist Folgende:
    img
  • t ist dabei der Winkel in Radianten. 360° entspricht 2Pi.
  • Zur Nutzung von Sinus & Cosinus muss das math Modul importiert werden
 import math

Ressourcen & Tutorials zum Thema

Art/Länge Titel Beschreibung Quelle
44min Python Crashcourse for Blender Guter Schnelleinstieg in Scripting mit Blender YouTube - Curtis Holt
Blender Python API Dokumentation Offizielle Blender API Dokumentation Blender Python API Dokumentation
21x je 5-20min Blender Python - Scripting Series Ausführlichere Serie zu Blender Scripting YouTube - Darkfall
15x je 5-20min Scripting for Artists Sehr gute aufgearbeitete Serie zu Blender Scripting und Addon Entwicklung - teilweise jedoch kostenpflichtig Blender Cloud - Dr. Sybren A. Stüvel
Einführung ins Programmieren mit Python Auf Deutsch pythonbuch.com
The Python 3.7 Tutorial Einstieg in Python Offizielle Python 3.7 Documentation
111min Python Tutorial 2020 Einführung in alle wichtigen Python Funktionalitäten (Blender unabhängig) YouTube - Derek Banas