Freigeben über


Betriebspersonal

Ausdrücke sind Sequenzen von Variablen und Literale, die von Operatoreninterpunktiert werden. Operatoren bestimmen, wie die Variablen und Literale kombiniert, verglichen, ausgewählt usw. werden. Zu den Operatoren gehören:

Operatorname Betriebspersonal
additive und multipliktive Operatoren +, -, *, /, %
Arrayoperator [i]
Zuordnungsoperatoren =, +=, -=, *=, /=, %=
Binäre Umwandlungen C-Regeln für Float- und Int-, C-Regeln oder HLSL-systeminterne Regeln für bool
Bitweise Operatoren ~, <<, >>, &, |, ^, <<=, >>=, &=, |=, ^=
boolesche mathematische Operatoren & &, ||, ?:
Umwandlungsoperator (Typ)
Kommaoperator ,
Vergleichsoperatoren <, >, ==, !=, <=, >=
Präfixoperatoren ++, --
Strukturoperator .
unäre Operatoren !, -, +

 

Viele der Operatoren sind pro Komponente, was bedeutet, dass der Vorgang unabhängig für jede Komponente jeder Variablen ausgeführt wird. Beispielsweise hat eine einzelne Komponentenvariable einen Vorgang ausgeführt. Andererseits hat eine Variable mit vier Komponenten vier Vorgänge ausgeführt, eine für jede Komponente.

Alle Operatoren, die einen Wert ausführen, z. B. +und *, funktionieren pro Komponente.

Die Vergleichsoperatoren erfordern eine einzelne Komponente, es sei denn, Sie verwenden die alle oder einer systeminternen Funktion mit einer Variablen mit mehreren Komponenten. Der folgende Vorgang schlägt fehl, da die If-Anweisung einen einzelnen Bool erfordert, aber einen Bool4 empfängt:

if (A4 < B4)

Die folgenden Vorgänge sind erfolgreich:

if ( any(A4 < B4) )
if ( all(A4 < B4) )

Die binären Umwandlungsoperatoren asfloat, asintusw. arbeit pro Komponente mit Ausnahme doppelt doppelten, deren spezielle Regeln dokumentiert sind.

Auswahloperatoren wie Punkt, Komma und Arrayklammern funktionieren nicht pro Komponente.

Umwandlungsoperatoren ändern die Anzahl der Komponenten. Die folgenden Umwandlungsvorgänge zeigen ihre Äquivalenz:

(float) i4 ->   float(i4.x)
(float4)i ->   float4(i, i, i, i)

Additive und multipliktive Operatoren

Die additiven und multiplizierten Operatoren sind: +, -, *, /, %

int i1 = 1;
int i2 = 2;
int i3 = i1 + i2;  // i3 = 3
i3 = i1 * i2;        // i3 = 1 * 2 = 2
i3 = i1/i2;       // i3 = 1/3 = 0.333. Truncated to 0 because i3 is an integer.
i3 = i2/i1;       // i3 = 2/1 = 2
float f1 = 1.0;
float f2 = 2.0f;
float f3 = f1 - f2; // f3 = 1.0 - 2.0 = -1.0
f3 = f1 * f2;         // f3 = 1.0 * 2.0 = 2.0
f3 = f1/f2;        // f3 = 1.0/2.0 = 0.5
f3 = f2/f1;        // f3 = 2.0/1.0 = 2.0

Der Modulusoperator gibt den Rest einer Division zurück. Dies erzeugt unterschiedliche Ergebnisse bei Verwendung von Ganzzahlen und Gleitkommazahlen. Ganze Reste, die Bruchzahlen sind, werden abgeschnitten.

int i1 = 1;
int i2 = 2;
i3 = i1 % i2;      // i3 = remainder of 1/2, which is 1
i3 = i2 % i1;      // i3 = remainder of 2/1, which is 0
i3 = 5 % 2;        // i3 = remainder of 5/2, which is 1
i3 = 9 % 2;        // i3 = remainder of 9/2, which is 1

Der Modulusoperator schneidet einen Bruch rest ab, wenn ganze Zahlen verwendet werden.

f3 = f1 % f2;      // f3 = remainder of 1.0/2.0, which is 0.5
f3 = f2 % f1;      // f3 = remainder of 2.0/1.0, which is 0.0

Der % Operator wird nur in Fällen definiert, in denen beide Seiten positiv sind oder beide Seiten negativ sind. Im Gegensatz zu C werden auch Gleitkommadatentypen sowie ganze Zahlen verwendet.

Arrayoperator

Der Arrayelementauswahloperator "[i]" wählt eine oder mehrere Komponenten in einem Array aus. Es handelt sich um eine Reihe von eckigen Klammern, die einen nullbasierten Index enthalten.

int arrayOfInts[4] = { 0,1,2,3 };
arrayOfInts[0] = 2;
arrayOfInts[1] = arrayOfInts[0];

Der Arrayoperator kann auch für den Zugriff auf einen Vektor verwendet werden.

float4 4D_Vector = { 0.0f, 1.0f, 2.0f, 3.0f  };         
float 1DFloat = 4D_Vector[1];          // 1.0f

Durch Hinzufügen eines zusätzlichen Indexes kann der Arrayoperator auch auf eine Matrix zugreifen.

float4x4 mat4x4 = {{0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} };
mat4x4[0][1] = 1.1f;
float 1DFloat = mat4x4[0][1];      // 0.0f

Der erste Index ist der nullbasierte Zeilenindex. Der zweite Index ist der nullbasierte Spaltenindex.

Zuordnungsoperatoren

Die Zuordnungsoperatoren sind: =, +=, -=, *=, /=

Variablen können Literalwerte zugewiesen werden:

int i = 1;            
float f2 = 3.1f; 
bool b = false;
string str = "string";

Variablen können auch das Ergebnis einer mathematischen Operation zugewiesen werden:

int i1 = 1;
i1 += 2;           // i1 = 1 + 2 = 3

Eine Variable kann auf beiden Seiten des Gleichheitszeichens verwendet werden:

float f3 = 0.5f;
f3 *= f3;          // f3 = 0.5 * 0.5 = 0.25

Division für Gleitkommavariablen ist wie erwartet, da dezimale Reste kein Problem darstellen.

float f1 = 1.0;
f1 /= 3.0f;        // f1 = 1.0/3.0 = 0.333

Achten Sie darauf, wenn Sie ganzzahlige Zahlen verwenden, die geteilt werden können, insbesondere, wenn sich die Abkürzung auf das Ergebnis auswirkt. Dieses Beispiel ist mit dem vorherigen Beispiel identisch, mit Ausnahme des Datentyps. Die Abkürzung führt zu einem sehr anderen Ergebnis.

int i1 = 1;
i1 /= 3;           // i1 = 1/3 = 0.333, which gets truncated to 0

Binäre Umwandlungen

Der Umwandlungsvorgang zwischen Int und Float konvertiert den numerischen Wert in die entsprechenden Darstellungen, die folgenden C-Regeln zum Abschneiden eines Int-Typs folgen. Das Umwandeln eines Werts von einem Float in ein Int und zurück zu einem Float führt zu einer verlustbehafteten Konvertierung basierend auf der Genauigkeit des Ziels.

Binäre Umwandlungen können auch mit Systeminternen Funktionen (DirectX HLSL)ausgeführt werden, wodurch die Bitdarstellung einer Zahl in den Zieldatentyp neu interpretiert wird.

asfloat() // Cast to float
asint()   // Cast to int 
asuint()  // Cast to uint

Bitweise Operatoren

HLSL unterstützt die folgenden bitweisen Operatoren, die dem gleichen Rang folgen wie C in Bezug auf andere Operatoren. In der folgenden Tabelle werden die Operatoren beschrieben.

Anmerkung

Bitweise Operatoren erfordern Shadermodell 4_0- mit Direct3D 10 und höherer Hardware.

 

Operator Funktion
~ Logisches Nicht
<< Linke Schicht
>> Umschalt rechts
& Logisch und
| Logisches Oder
^ Logischer Xor
<<= Umschalt nach links gleich
>>= Umschalt rechts gleich
&= Und gleich
|= Oder gleich
^= Xor gleich

 

Bitweise Operatoren sind so definiert, dass sie nur für Int- und Uint-Datentypen verwendet werden. Wenn Sie versuchen, bitweise Operatoren für float zu verwenden, oder strukturieren Sie Datentypen, führt zu einem Fehler.

Boolesche mathematische Operatoren

Die booleschen mathematischen Operatoren sind: &&, ||, ?:

bool b1 = true;
bool b2 = false;
bool b3 = b1 && b2 // b3 = true AND false = false
b3 = b1 || b2                // b3 = true OR false = true

Im Gegensatz zur Kurzschlussauswertung von &&, ||und ?: in C werden HLSL-Ausdrücke niemals kurzkreisen, da sie Vektorvorgänge sind. Alle Seiten des Ausdrucks werden immer ausgewertet.

Boolesche Operatoren funktionieren pro Komponente. Dies bedeutet: Wenn Sie zwei Vektoren vergleichen, ist das Ergebnis ein Vektor, der das boolesche Ergebnis des Vergleichs für jede Komponente enthält.

Bei Ausdrücken, die boolesche Operatoren verwenden, wird die Größe und der Komponententyp jeder Variablen höhergestuft, bevor der Vorgang eintritt. Der höhergestufte Typ bestimmt die Auflösung, an der der Vorgang stattfindet, sowie den Ergebnistyp des Ausdrucks. Beispielsweise würde ein Int3 + Float-Ausdruck zur Auswertung in float3 + float3 heraufgestuft, und das Ergebnis wäre vom Typ float3.

Umwandlungsoperator

Ein Ausdruck, der einem Typnamen in Klammern vorausgeht, ist eine explizite Typ cast. Ein Typ wandelt den ursprünglichen Ausdruck in den Datentyp der Umwandlung um. Im Allgemeinen können die einfachen Datentypen in komplexere Datentypen umgewandelt werden (mit einer Heraufstufungs-Umwandlung), aber nur einige komplexe Datentypen können in einfache Datentypen umgewandelt werden (mit einer Herabstufung).

Nur rechtsseitiges Umwandlungsmuster ist zulässig. Beispielsweise sind Ausdrücke wie (int)myFloat = myInt; unzulässig. Verwenden Sie stattdessen myFloat = (float)myInt;.

Der Compiler führt auch implizite Typ cast durch. Die folgenden beiden Ausdrücke sind z. B. gleichwertig:

int2 b = int2(1,2) + 2;
int2 b = int2(1,2) + int2(2,2);

Kommaoperator

Der Kommaoperator (,) trennt einen oder mehrere Ausdrücke, die in der Reihenfolge ausgewertet werden sollen. Der Wert des letzten Ausdrucks in der Sequenz wird als Wert der Sequenz verwendet.

Hier ist ein Fall, der aufmerksamkeitswürdig ist. Wenn der Konstruktortyp versehentlich von der rechten Seite des Gleichheitszeichens weggelassen wird, enthält die rechte Seite jetzt vier Ausdrücke, die durch drei Kommas getrennt sind.

// Instead of using a constructor
float4 x = float4(0,0,0,1); 

// The type on the right side is accidentally left off
float4 x = (0,0,0,1); 

Der Kommaoperator wertet einen Ausdruck von links nach rechts aus. Dies reduziert die rechte Seite auf:

float4 x = 1; 

HLSL verwendet in diesem Fall skalare Heraufstärkung, sodass das Ergebnis wie folgt lautet:

float4 x = float4(1,1,1,1);

In diesem Fall ist das Verlassen des float4-Typs von der rechten Seite wahrscheinlich ein Fehler, dass der Compiler nicht erkennen kann, da dies eine gültige Anweisung ist.

Vergleichsoperatoren

Die Vergleichsoperatoren sind: <, >, ==, !=, <=, >=.

Vergleichen Sie Werte, die größer als (oder kleiner als) eines skalaren Werts sind:

if( dot(lightDirection, normalVector) > 0 )
   // Do something; the face is lit
if( dot(lightDirection, normalVector) < 0 )
   // Do nothing; the face is backwards

Oder vergleichen Sie werte gleich (oder nicht gleich) einem Skalarwert:

if(color.a == 0)
   // Skip processing because the face is invisible

if(color.a != 0)
   // Blend two colors together using the alpha value

Oder kombinieren Sie beide Werte und vergleichen Sie Werte, die größer oder gleich (oder kleiner als oder gleich) beliebiger Skalarwert sind:

if( position.z >= oldPosition.z )
   // Skip the new face because it is behind the existing face
if( currentValue <= someInitialCondition )
   // Reset the current value to its initial condition

Jeder dieser Vergleiche kann mit jedem skalaren Datentyp erfolgen.

Wenn Sie Vergleichsoperatoren mit Vektor- und Matrixtypen verwenden möchten, verwenden Sie die alle oder jeder systeminternen Funktion.

Dieser Vorgang schlägt fehl, da die If-Anweisung einen einzelnen Bool erfordert, aber einen Bool4 empfängt:

if (A4 < B4)

Diese Vorgänge sind erfolgreich:

if ( any(A4 < B4) )
if ( all(A4 < B4) )

Präfix- oder Postfixoperatoren

Die Präfix- und Postfixoperatoren sind: ++, --. Präfixoperatoren ändern den Inhalt der Variablen, bevor der Ausdruck ausgewertet wird. Postfix-Operatoren ändern den Inhalt der Variablen, nachdem der Ausdruck ausgewertet wurde.

In diesem Fall verwendet eine Schleife den Inhalt von i, um die Anzahl der Schleifen nachzuverfolgen.

float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };

for (int i = 0; i<4; )
{
    arrayOfFloats[i++] *= 2; 
}

Da der Postfix-Inkrementoperator (++) verwendet wird, wird arrayOfFloats[i] mit 2 multipliziert, bevor i erhöht wird. Dies könnte leicht neu angeordnet werden, um den Präfixinkrementierungsoperator zu verwenden. Dies ist schwieriger zu lesen, obwohl beide Beispiele gleichwertig sind.

float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };

for (int i = 0; i<4; )
{
    arrayOfFloats[++i - 1] *= 2; 
}

Da der Präfixoperator (++) verwendet wird, wird arrayOfFloats[i+1 - 1] mit 2 multipliziert, nachdem i erhöht wurde.

Der Präfix-Decrement- und postfix-Decrement-Operator (--) werden in derselben Reihenfolge wie der Inkrementoperator angewendet. Der Unterschied besteht darin, dass die Dekrementierung 1 subtrahiert, anstatt 1 hinzuzufügen.

Strukturoperator

Der Strukturelementauswahloperator (.) ist ein Punkt. Aufgrund dieser Struktur:

struct position
{
float4 x;
float4 y;
float4 z;
};

Es kann wie folgt gelesen werden:

struct position pos = { 1,2,3 };

float 1D_Float = pos.x
1D_Float = pos.y

Jedes Element kann mit dem Strukturoperator gelesen oder geschrieben werden:

struct position pos = { 1,2,3 };
pos.x = 2.0f;
pos.z = 1.0f;       // z = 1.0f
pos.z = pos.x      // z = 2.0f

Unäre Operatoren

Die unären Operatoren sind: , -, +

Unäre Operatoren werden für einen einzelnen Operanden ausgeführt.

bool b = false;
bool b2 = !b;      // b2 = true
int i = 2;
int i2 = -i;       // i2 = -2
int j = +i2;       // j = +2

Rangfolge des Operators

Wenn ein Ausdruck mehrere Operatoren enthält, bestimmt die Operatorrangfolge die Reihenfolge der Auswertung. Die Rangfolge des Operators für HLSL folgt der gleichen Rangfolge wie C.

Bemerkungen

Geschweifte Klammern ({,}) beginnen und beenden einen Anweisungsblock. Wenn ein Anweisungsblock eine einzelne Anweisung verwendet, sind die geschweiften Klammern optional.

-Anweisungen (DirectX HLSL)