This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Materialien legen fest, wie eine grafische Komponente (component), etwa ein Sprite, eine Kachelkarte (tile map), eine Schriftart, ein GUI-Knoten oder ein Modell, gerendert werden soll.
Ein Material enthält Tags, also Informationen, mit denen die Rendering-Pipeline die zu rendernden Objekte auswählt. Es enthält außerdem Referenzen auf Shader-Programme, die über den verfügbaren Grafiktreiber kompiliert und auf die Grafikhardware hochgeladen werden. Sie werden in jedem Frame ausgeführt, wenn die Komponente gerendert wird.
Um ein Material zu erstellen, führe im Browser Assets einen Rechtsklick auf einen Zielordner aus und wähle New... ▸ Material. (Du kannst auch im Menü File ▸ New... und anschließend Material wählen.) Benenne die neue Materialdatei und drücke Ok.

Das neue Material wird im Material Editor geöffnet.

Die Materialdatei enthält die folgenden Informationen:
render.enable_material() verwendet. Der Name sollte eindeutig sein..vp), die beim Rendern mit diesem Material verwendet wird. Das Vertex-Shader-Programm wird auf der GPU für jeden Vertex der Primitive einer Komponente ausgeführt. Es berechnet die Bildschirmposition jedes Vertex und gibt optional auch „varying“-Variablen aus, die interpoliert und an das Fragment-Programm übergeben werden..fp), die beim Rendern mit diesem Material verwendet wird. Das Programm läuft auf der GPU für jedes Fragment (Pixel) eines Primitivs und bestimmt die Farbe jedes Fragments. Dies geschieht üblicherweise durch Texturabfragen und Berechnungen anhand von Eingabevariablen (Varying-Variablen oder Konstanten).render.predicate() verwendet, um Komponenten zusammenzufassen, die gemeinsam gezeichnet werden sollen. Wie das geht, erfährst du in der Rendering-Dokumentation. In einem Projekt kannst du höchstens 32 Tags verwenden.Shader-Attribute (auch Vertex-Datenströme oder Vertex-Attribute genannt) legen fest, wie die GPU Vertices aus dem Speicher abruft, um Geometrie zu rendern. Der Vertex-Shader gibt mit dem Schlüsselwort attribute eine Menge von Datenströmen an. In den meisten Fällen erzeugt und bindet Defold die Daten im Hintergrund automatisch anhand der Namen dieser Datenströme. In manchen Fällen möchtest du jedoch zusätzliche Daten pro Vertex übergeben, um einen bestimmten Effekt zu erzielen, dessen Daten die Engine nicht erzeugt. Ein Vertex-Attribut kann mit den folgenden Feldern konfiguriert werden:
SEMANTIC_TYPE_COLOR angibst, zeigt der Editor eine Farbauswahl an. Die Engine übergibt die Daten dabei weiterhin unverändert an den Shader.
SEMANTIC_TYPE_NONE Der standardmäßige semantische Typ. Hat keinen weiteren Einfluss auf das Attribut, außer die Materialdaten für das Attribut direkt an den Vertex-Puffer zu übergeben (Standard)SEMANTIC_TYPE_POSITION Erzeugt Positionsdaten pro Vertex für das Attribut. Kann zusammen mit dem Koordinatensystem verwendet werden, um der Engine vorzugeben, wie die Positionen berechnet werdenSEMANTIC_TYPE_TEXCOORD Erzeugt Texturkoordinaten pro Vertex für das AttributSEMANTIC_TYPE_PAGE_INDEX Erzeugt Seitenindizes pro Vertex für das AttributSEMANTIC_TYPE_COLOR Beeinflusst, wie der Editor das Attribut interpretiert. Wenn ein Attribut mit Farbsemantik konfiguriert ist, wird im Inspektor ein Farbauswahlfeld angezeigtSEMANTIC_TYPE_NORMAL Erzeugt Normalendaten pro Vertex für das AttributSEMANTIC_TYPE_TANGENT Erzeugt Tangentendaten pro Vertex für das AttributSEMANTIC_TYPE_WORLD_MATRIX Erzeugt Weltmatrixdaten pro Vertex für das AttributSEMANTIC_TYPE_NORMAL_MATRIX Erzeugt Normalenmatrixdaten pro Vertex für das AttributSEMANTIC_TYPE_TEXTURE_TRANSFORM_2D Erzeugt eine 3x3-Texturtransformationsmatrix pro Vertex für das Attribut. Für Partikelkomponenten stellt die Engine eine Matrix bereit, die Koordinaten für die Bildeigenschaft der Komponente in das Atlas-Koordinatensystem transformiert. Für Sprite-Komponenten stellt die Engine für jedes von der Komponente verwendete Bild eine Matrix bereit (bei Verwendung mehrerer Texturen). Für Modellkomponenten wird eine Einheitsmatrix bereitgestellt.TYPE_BYTE Vorzeichenbehaftete 8-Bit-Byte-WerteTYPE_UNSIGNED_BYTE Vorzeichenlose 8-Bit-Byte-WerteTYPE_SHORT Vorzeichenbehaftete 16-Bit-Short-WerteTYPE_UNSIGNED_SHORT Vorzeichenlose 16-Bit-Short-WerteTYPE_INT Vorzeichenbehaftete GanzzahlwerteTYPE_UNSIGNED_INT Vorzeichenlose GanzzahlwerteTYPE_FLOAT Gleitkommawerte (Standard)VECTOR_TYPE_SCALAR Einzelner SkalarwertVECTOR_TYPE_VEC2 2D-VektorVECTOR_TYPE_VEC3 3D-VektorVECTOR_TYPE_VEC4 4D-Vektor (Standard)VECTOR_TYPE_MAT2 2D-MatrixVECTOR_TYPE_MAT3 3D-MatrixVECTOR_TYPE_MAT4 4D-MatrixVertex Einmal pro Vertex; ein Positionsattribut wird beispielsweise üblicherweise für jeden Vertex im Mesh an die Vertex-Funktion übergeben (Standard)Instance Einmal pro Instanz; ein Weltmatrixattribut wird beispielsweise üblicherweise einmal pro Instanz an die Vertex-Funktion übergebenMit benutzerdefinierten Attributen kannst du auch den Speicherbedarf sowohl auf der CPU als auch auf der GPU verringern, indem du die Datenströme für einen kleineren Datentyp oder eine andere Elementanzahl konfigurierst.
Das Materialsystem weist zur Laufzeit für eine bestimmte Menge von Attributnamen automatisch einen standardmäßigen semantischen Typ anhand des Namens zu:
position - semantischer Typ: SEMANTIC_TYPE_POSITIONtexcoord0 - semantischer Typ: SEMANTIC_TYPE_TEXCOORDtexcoord1 - semantischer Typ: SEMANTIC_TYPE_TEXCOORDpage_index - semantischer Typ: SEMANTIC_TYPE_PAGE_INDEXcolor - semantischer Typ: SEMANTIC_TYPE_COLORnormal - semantischer Typ: SEMANTIC_TYPE_NORMALtangent - semantischer Typ: SEMANTIC_TYPE_TANGENTmtx_world - semantischer Typ: SEMANTIC_TYPE_WORLD_MATRIXmtx_normal - semantischer Typ: SEMANTIC_TYPE_NORMAL_MATRIXmtx_texture_transform_2d - semantischer Typ: SEMANTIC_TYPE_TEXTURE_TRANSFORM_2DWenn du im Material Einträge für diese Attribute anlegst, wird der standardmäßige semantische Typ durch den im Materialeditor konfigurierten Typ überschrieben.
Ähnlich wie benutzerdefinierte Shader-Konstanten kannst du auch Vertex-Attribute zur Laufzeit aktualisieren, indem du go.get, go.set und go.animate aufrufst:

go.set("#sprite", "tint", vmath.vector4(1,0,0,1))
go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
Beim Aktualisieren von Vertex-Attributen gibt es jedoch einige Einschränkungen: Ob eine Komponente den Wert verwenden kann, hängt vom semantischen Typ des Attributs ab. Eine Sprite-Komponente unterstützt beispielsweise SEMANTIC_TYPE_POSITION. Wenn du ein Attribut mit diesem semantischen Typ aktualisierst, ignoriert die Komponente den überschriebenen Wert, da der semantische Typ vorgibt, dass die Daten immer aus der Position des Sprites erzeugt werden sollen.
Modellkomponenten stellen benutzerdefinierte Materialattribute ebenfalls über go.get(), go.set() und go.animate() bereit. Nachdem du beispielsweise ein Attribut namens my_attribute im Modellmaterial definiert hast:
go.set("#model", "my_attribute", vmath.vector4(1, 0, 0, 1))
go.animate("#model", "my_attribute", go.PLAYBACK_LOOP_PINGPONG,
vmath.vector4(0, 1, 0, 1), go.EASING_LINEAR, 2)
Bei einem Modell mit mehreren Meshes kann derzeit nur das erste Mesh auf diese Weise angesprochen werden. Das Aktualisieren eines nicht instanzierten Attributs pro Vertex kann außerdem dazu führen, dass Vertex-Daten in einem zur Mesh-Größe proportionalen Umfang neu erstellt und hochgeladen werden. Häufige Aktualisierungen können daher bei großen Meshes aufwendig sein.
Wenn ein Vertex-Attribut ein Skalar oder ein anderer Vektortyp als Vec4 ist, kannst du die Daten trotzdem mit go.set setzen:
-- The last two components in the vec4 will not be used!
go.set("#sprite", "sprite_position_2d", vmath.vector4(my_x,my_y,0,0))
go.animate("#sprite", "sprite_position_2d", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,2,0,0), go.EASING_LINEAR, 2)
Dasselbe gilt für Matrixattribute: Wenn das Attribut einen anderen Matrixtyp als Mat4 hat, kannst du die Daten trotzdem mit go.set setzen.
Ein Texturtransformationsattribut verwenden, um UV-Koordinaten in das Atlas-Koordinatensystem umzuwandeln:
#version 140
in vec3 position;
in vec4 texcoord0;
in mat3 texture_transform_2d;
out vec2 var_texcoord0;
void main()
{
// Extract position from the transform
vec2 atlas_pos = texture_transform_2d[2].xy;
// Extract the scale from the transform
vec2 atlas_size = vec2(
length(texture_transform_2d[0].xy),
length(texture_transform_2d[1].xy)
);
// convert to local UV (0..1)
vec2 localUV = (texcoord0 - atlas_pos) / atlas_size;
// Alternatively, if the UV coordinates already are in the 0..1 range,
// you can transform into atlas space directly by multiplying the transform:
vec2 transformedUv = texture_transform_2d * texcoord0;
// Pass the value into the fragment shader
var_texcoord0 = localUV;
// ... rest of vertex shader
}
Instancing ist eine Technik, mit der mehrere Kopien desselben Objekts in einer Szene effizient gezeichnet werden. Anstatt bei jeder Verwendung eine separate Kopie des Objekts zu erzeugen, kann die Grafik-Engine mit Instancing ein einzelnes Objekt erstellen und es mehrfach wiederverwenden. In einem Spiel mit einem großen Wald kannst du beispielsweise ein einziges Baummodell erstellen und es dann hunderte oder tausende Male mit unterschiedlichen Positionen und Skalierungen platzieren, anstatt für jeden Baum ein eigenes Modell anzulegen. Der Wald kann nun mit einem einzigen Zeichenaufruf (draw call) gerendert werden statt mit einzelnen Zeichenaufrufen für jeden Baum.
Instancing ist derzeit nur für Modellkomponenten verfügbar.
Instancing wird automatisch aktiviert, wenn es möglich ist. Defold setzt stark darauf, Zeichenoperationen mit gleichem Zustand möglichst weitgehend zu bündeln. Damit Instancing funktioniert, müssen einige Voraussetzungen erfüllt sein:
render.enable_material gesetzt wurdeDamit ein Vertex-Attribut pro Instanz wiederholt wird, muss Step function auf Instance gesetzt sein. Bei bestimmten semantischen Typen geschieht dies automatisch anhand des Namens (siehe die Tabelle Standardsemantik von Attributen weiter oben). Du kannst dies aber auch im Materialeditor manuell einstellen, indem du Step function auf Instance setzt.
Als einfaches Beispiel enthält die folgende Szene vier Spielobjekte (game objects) mit jeweils einer Modellkomponente:

Das Material ist wie folgt konfiguriert, mit einem einzelnen benutzerdefinierten Vertex-Attribut, das pro Instanz wiederholt wird:

Im Vertex-Shader sind mehrere Attribute pro Instanz angegeben:
// Per vertex attributes
attribute highp vec4 position;
attribute mediump vec2 texcoord0;
attribute mediump vec3 normal;
// Per instance attributes
attribute mediump mat4 mtx_world;
attribute mediump mat4 mtx_normal;
attribute mediump vec4 instance_color;
Beachte, dass mtx_world und mtx_normal standardmäßig mit der Schritt-Funktion Instance konfiguriert werden. Du kannst dies im Materialeditor ändern, indem du für sie einen Eintrag hinzufügst und Step function auf Vertex setzt. Dadurch wird das Attribut pro Vertex statt pro Instanz wiederholt.
Um zu überprüfen, ob Instancing in diesem Fall funktioniert, kannst du den Web-Profiler verwenden. Da sich die Instanzen des Quaders in diesem Fall nur durch die Attribute pro Instanz unterscheiden, kann er mit einem einzigen Zeichenaufruf gerendert werden:

OpenGL 3.1 auf Desktop-Geräten und OpenGL ES 3.0 auf Mobilgeräten bieten Instancing als Kernfunktion. Ältere OpenGL-ES- und WebGL-Kontexte können es weiterhin über eine Erweiterung wie ANGLE_instanced_arrays unterstützen; andere ältere Adapter unterstützen es nicht. Wenn Instancing nicht verfügbar ist, funktioniert das Rendering standardmäßig weiterhin, kann jedoch weniger leistungsfähig sein.
Verwende graphics.get_adapter_info(), um die Unterstützung zu erkennen und bei Bedarf ein weniger aufwendiges Material zu wählen oder Inhalte mit vielen Instanzen auszulassen. Das Feld features ist ein Array der unterstützten Funktionskonstanten, keine Tabelle mit diesen Konstanten als Schlüsseln:
local function has_context_feature(feature)
local adapter_info = graphics.get_adapter_info()
for _, supported_feature in ipairs(adapter_info.features) do
if supported_feature == feature then
return true
end
end
return false
end
local instancing_supported = has_context_feature(
graphics.CONTEXT_FEATURE_INSTANCING
)
Shader-Konstanten oder „Uniforms“ sind Werte, die die Engine an Vertex- und Fragment-Shader-Programme übergibt. Um eine Konstante zu verwenden, definierst du sie in der Materialdatei entweder als Eigenschaft Vertex Constant oder als Eigenschaft Fragment Constant. Entsprechende uniform-Variablen müssen im Shader-Programm definiert werden. Die folgenden Konstanten können in einem Material gesetzt werden:
CONSTANT_TYPE_WORLDCONSTANT_TYPE_VIEWCONSTANT_TYPE_PROJECTIONCONSTANT_TYPE_VIEWPROJCONSTANT_TYPE_WORLDVIEWCONSTANT_TYPE_WORLDVIEWPROJCONSTANT_TYPE_WORLD_INVERSECONSTANT_TYPE_VIEW_INVERSECONSTANT_TYPE_PROJECTION_INVERSECONSTANT_TYPE_VIEWPROJ_INVERSECONSTANT_TYPE_WORLDVIEW_INVERSECONSTANT_TYPE_WORLDVIEWPROJ_INVERSECONSTANT_TYPE_NORMALCONSTANT_TYPE_TIMEvector4, bei dem .x die seit dem Start der Engine verstrichene Zeit und .y die Zeitdifferenz zum vorherigen Frame enthält. .z und .w sind derzeit null. Die Engine aktualisiert diesen Wert automatisch; er muss nicht mit go.set() aktualisiert werden. Ein Beispiel findest du im Shadertoy-Tutorial.
Deklariere eine Time-Konstante namens time in einem modernen GLSL-Uniform-Block:
uniform fragment_inputs
{
vec4 time;
};
CONSTANT_TYPE_USERBeispiel:
go.set("#sprite", "tint", vmath.vector4(1,0,0,1))
go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
CONSTANT_TYPE_USER_MATRIX4Beispiel:
go.set("#sprite", "m", vmath.matrix4())
Lies und schreibe die Materialkonstanten eines Knotens innerhalb eines GUI-Skripts mit gui.get() und gui.set() statt mit den go-Funktionen. Vektorkomponenten, Matrixkonstanten und Konstantenarrays werden unterstützt. Array-Indizes in der Optionstabelle beginnen bei 1:
local node = gui.get_node("button")
local tint = gui.get(node, "tint")
gui.set(node, "tint.x", 0.5)
gui.set(node, "light_matrix", vmath.matrix4())
gui.set(node, "tint_array", vmath.vector4(1, 0, 0, 1), { index = 1 })
Damit eine Materialkonstante vom Typ CONSTANT_TYPE_USER oder CONSTANT_TYPE_USER_MATRIX4 über go.get() und go.set() oder gui.get() und gui.set() verfügbar ist, muss sie im Shader-Programm verwendet werden. Wenn die Konstante im Material definiert ist, aber im Programm nicht verwendet wird, wird sie aus dem Material entfernt und ist zur Laufzeit nicht verfügbar.
Sampler dienen dazu, Farbinformationen aus einer Textur (einer Kachelquelle oder einem Atlas) abzutasten. Die Farbinformationen können anschließend für Berechnungen im Shader-Programm verwendet werden.
Sprite-, Kachelkarten-, GUI- und Partikeleffektkomponenten binden ihre Bildtextur automatisch an den zuerst deklarierten sampler2D. Sprite-Komponenten unterstützen außerdem mehrere Texturen: Jeder im Material deklarierte Sampler wird zu einem benannten Bildplatz in der Sprite-Komponente. Die erste Textur liefert die Animationsdaten des Sprites und steuert die Einzelbildfolge. Für jedes Einzelbild wird anhand seiner Bild-ID das entsprechende Bild in jeder zusätzlichen Textur gesucht, die jeweils ihre eigenen UV-Koordinaten liefert. Die zugewiesenen Atlanten oder Kachelquellen sollten daher übereinstimmende Einzelbild-IDs und ähnlich geformte Bilder enthalten; unterschiedliche polygonal gepackte Formen können zum Übergreifen benachbarter Texturpixel (texture bleeding) führen. Weitere Informationen findest du unter Sprites mit mehreren Texturen.
Bei einer Komponente oder einem Rendering-Arbeitsablauf, der keinen zusätzlichen Texturplatz bereitstellt, kannst du mit render.enable_texture() zusätzliche Textur-Sampler aus dem Render-Skript binden.
![]()
-- mysprite.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D MY_SAMPLER;
void main()
{
gl_FragColor = texture2D(MY_SAMPLER, var_texcoord0.xy);
}
Du kannst die Sampler-Einstellungen einer Komponente festlegen, indem du den Sampler mit seinem Namen in der Materialdatei hinzufügst. Wenn du deinen Sampler nicht in der Materialdatei konfigurierst, werden die globalen Projekteinstellungen unter graphics verwendet.

Für Modellkomponenten musst du deine Sampler mit den gewünschten Einstellungen in der Materialdatei angeben. Anschließend kannst du im Editor Texturen für jede Modellkomponente setzen, die das Material verwendet:

-- mymodel.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D TEXTURE_1;
uniform lowp sampler2D TEXTURE_2;
void main()
{
lowp vec4 color1 = texture2D(TEXTURE_1, var_texcoord0.xy);
lowp vec4 color2 = texture2D(TEXTURE_2, var_texcoord0.xy);
gl_FragColor = color1 * color2;
}

sampler2D übereinstimmen.WRAP_MODE_REPEAT wiederholt Texturdaten außerhalb des Bereichs [0,1].WRAP_MODE_MIRRORED_REPEAT wiederholt Texturdaten außerhalb des Bereichs [0,1], wobei jede zweite Wiederholung gespiegelt wird.WRAP_MODE_CLAMP_TO_EDGE begrenzt Texturdaten für Werte größer als 1.0 auf 1.0 und setzt alle Werte kleiner als 0.0 auf 0.0—das heißt, die Randpixel werden bis zum Rand wiederholt.Default verwendet die Standardfilteroption, die in der Datei game.project unter Graphics als Default Texture Min Filter und Default Texture Mag Filter angegeben ist.FILTER_MODE_NEAREST verwendet das Texel, dessen Koordinaten dem Mittelpunkt des Pixels am nächsten liegen.FILTER_MODE_LINEAR berechnet einen gewichteten linearen Mittelwert des 2x2-Arrays der Texel, die dem Mittelpunkt des Pixels am nächsten liegen.FILTER_MODE_NEAREST_MIPMAP_NEAREST wählt den nächstgelegenen Texelwert innerhalb einer einzelnen Mipmap.FILTER_MODE_NEAREST_MIPMAP_LINEAR wählt das nächstgelegene Texel in den beiden am besten passenden Mipmaps und interpoliert anschließend linear zwischen diesen beiden Werten.FILTER_MODE_LINEAR_MIPMAP_NEAREST interpoliert linear innerhalb einer einzelnen Mipmap.FILTER_MODE_LINEAR_MIPMAP_LINEAR berechnet den Wert in jeder von zwei Mipmaps durch lineare Interpolation und interpoliert anschließend linear zwischen diesen beiden Werten.Beim Zeichnen ruft die Rendering-Pipeline Konstantenwerte aus einem standardmäßigen Systemkonstantenpuffer ab. Du kannst einen benutzerdefinierten Konstantenpuffer erstellen, um die Standardkonstanten zu überschreiben und die Uniforms des Shader-Programms stattdessen im Render-Skript programmatisch zu setzen:
self.constants = render.constant_buffer() -- <1>
self.constants.tint = vmath.vector4(1, 0, 0, 1) -- <2>
...
render.draw(self.my_pred, {constants = self.constants}) -- <3>
tint auf leuchtendes RotBeachte, dass du die Konstantenelemente des Puffers wie die Einträge einer gewöhnlichen Lua-Tabelle ansprichst, den Puffer jedoch nicht mit pairs() oder ipairs() durchlaufen kannst.