Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Expressões são sequências de variáveis e literais pontuados por operadores . Os operadores determinam como as variáveis e literais são combinados, comparados, selecionados e assim por diante. Os operadores incluem:
Nome do operador | Operadores |
---|---|
operadores aditivos e multiplicativos | +, -, *, /, % |
operador de matriz | [i] |
operadores de atribuição de | =, +=, -=, *=, /=, %= |
conversões binárias | Regras C para float e int, regras C ou intrínsecos HLSL para bool |
operadores bit a bit | ~, <<, >>, &, |, ^, <<=, >>=, &=, |=, ^= |
operadores matemáticos boolianos | & &, ||, ?: |
operador de conversão | (tipo) |
operador de vírgula | , |
operadores de comparação | <, >, ==, !=, <=, >= |
operadores de prefixo ou postfixo | ++, -- |
operador de estrutura | . |
operadores unários | !, -, + |
Muitos dos operadores são por componente, o que significa que a operação é executada independentemente para cada componente de cada variável. Por exemplo, uma única variável de componente tem uma operação executada. Por outro lado, uma variável de quatro componentes tem quatro operações executadas, uma para cada componente.
Todos os operadores que fazem algo com o valor, como + e *, funcionam por componente.
Os operadores de comparação exigem que um único componente funcione, a menos que você use o todos os ou qualquer função intrínseca com uma variável de vários componentes. A operação a seguir falha porque a instrução if requer um único bool, mas recebe um bool4:
if (A4 < B4)
As seguintes operações são bem-sucedidas:
if ( any(A4 < B4) )
if ( all(A4 < B4) )
Os operadores de conversão binária à tona, asint e assim por trabalho por componente, exceto por assolúveis cujas regras especiais estão documentadas.
Os operadores de seleção, como colchetes de ponto, vírgula e matriz, não funcionam por componente.
Operadores de conversão alteram o número de componentes. As seguintes operações de conversão mostram sua equivalência:
(float) i4 -> float(i4.x)
(float4)i -> float4(i, i, i, i)
Operadores aditivos e multiplicativos
Os operadores aditivos e multiplicativos são: +, -, *, /, %
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
O operador modulus retorna o restante de uma divisão. Isso produz resultados diferentes ao usar números inteiros e de ponto flutuante. Os restantes inteiros fracionários serão truncados.
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
O operador modulus trunca um restante fracionário ao usar inteiros.
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
O operador % é definido somente em casos em que ambos os lados são positivos ou ambos os lados são negativos. Ao contrário de C, ele também opera em tipos de dados de ponto flutuante, bem como inteiros.
Operador de matriz
O operador de seleção de membro de matriz "[i]" seleciona um ou mais componentes em uma matriz. É um conjunto de colchetes que contêm um índice baseado em zero.
int arrayOfInts[4] = { 0,1,2,3 };
arrayOfInts[0] = 2;
arrayOfInts[1] = arrayOfInts[0];
O operador de matriz também pode ser usado para acessar um vetor.
float4 4D_Vector = { 0.0f, 1.0f, 2.0f, 3.0f };
float 1DFloat = 4D_Vector[1]; // 1.0f
Ao adicionar um índice adicional, o operador de matriz também pode acessar uma matriz.
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
O primeiro índice é o índice de linha baseado em zero. O segundo índice é o índice de coluna baseado em zero.
Operadores de atribuição
Os operadores de atribuição são: =, +=, -=, *=, /=
As variáveis podem receber valores literais:
int i = 1;
float f2 = 3.1f;
bool b = false;
string str = "string";
Variáveis também podem ser atribuídas ao resultado de uma operação matemática:
int i1 = 1;
i1 += 2; // i1 = 1 + 2 = 3
Uma variável pode ser usada em ambos os lados do sinal de igual:
float f3 = 0.5f;
f3 *= f3; // f3 = 0.5 * 0.5 = 0.25
A divisão para variáveis de ponto flutuante é o esperado porque os restos decimais não são um problema.
float f1 = 1.0;
f1 /= 3.0f; // f1 = 1.0/3.0 = 0.333
Tenha cuidado se você estiver usando inteiros que podem ser divididos, especialmente quando o truncamento afetar o resultado. Este exemplo é idêntico ao exemplo anterior, exceto pelo tipo de dados. O truncamento causa um resultado muito diferente.
int i1 = 1;
i1 /= 3; // i1 = 1/3 = 0.333, which gets truncated to 0
Conversões binárias
A operação de conversão entre o int e o float converterá o valor numérico nas representações apropriadas seguindo as regras C para truncar um tipo int. A conversão de um valor de um float para um int e de volta para um float resultará em uma conversão de perda com base na precisão do destino.
Conversões binárias também podem ser executadas usando directx HLSL (FUNÇÕES Intrínsecas), que reinterpretam a representação de bit de um número no tipo de dados de destino.
asfloat() // Cast to float
asint() // Cast to int
asuint() // Cast to uint
Operadores bit a bit
O HLSL dá suporte aos seguintes operadores bit a bit, que seguem a mesma precedência que C em relação a outros operadores. A tabela a seguir descreve os operadores.
Nota
Os operadores bit a bit exigem modelo de sombreador 4_0 com o Direct3D 10 e hardware superior.
Operador | Função |
---|---|
~ | Não Lógico |
<< | Deslocamento para a esquerda |
>> | Deslocamento para a direita |
& | Lógico e |
| | Lógico ou |
^ | Xor lógico |
<<= | Deslocamento à esquerda igual |
>>= | Deslocamento à Direita Igual |
&= | E igual |
|= | Ou Igual |
^= | Xor Igual |
Os operadores bit a bit são definidos para operar somente em tipos de dados int e uint. A tentativa de usar operadores bit a bit em tipos de dados float ou struct resultará em um erro.
Operadores de matemática booliana
Os operadores de matemática booliana são: &&, ||, ?:
bool b1 = true;
bool b2 = false;
bool b3 = b1 && b2 // b3 = true AND false = false
b3 = b1 || b2 // b3 = true OR false = true
Ao contrário da avaliação de curto-circuito de &&, ||e ?: em C, as expressões HLSL nunca fazem curto-circuito em uma avaliação porque são operações de vetor. Todos os lados da expressão são sempre avaliados.
Os operadores boolianos funcionam por componente. Isso significa que, se você comparar dois vetores, o resultado será um vetor que contém o resultado booliano da comparação para cada componente.
Para expressões que usam operadores boolianos, o tamanho e o tipo de componente de cada variável são promovidos para serem os mesmos antes da operação ocorrer. O tipo promovido determina a resolução na qual a operação ocorre, bem como o tipo de resultado da expressão. Por exemplo, uma expressão int3 + float seria promovida a float3 + float3 para avaliação, e seu resultado seria do tipo float3.
Operador Cast
Uma expressão precedida por um nome de tipo entre parênteses é uma conversão de tipo explícita. Uma conversão de tipo converte a expressão original no tipo de dados da conversão. Em geral, os tipos de dados simples podem ser convertidos para os tipos de dados mais complexos (com uma conversão de promoção), mas apenas alguns tipos de dados complexos podem ser convertidos em tipos de dados simples (com uma conversão de rebaixamento).
Somente a conversão de tipo do lado direito é legal. Por exemplo, expressões como (int)myFloat = myInt;
são ilegais. Em vez disso, use myFloat = (float)myInt;
.
O compilador também executa a conversão de tipo implícita. Por exemplo, as duas expressões a seguir são equivalentes:
int2 b = int2(1,2) + 2;
int2 b = int2(1,2) + int2(2,2);
Operador de vírgula
O operador de vírgula (,) separa uma ou mais expressões que devem ser avaliadas em ordem. O valor da última expressão na sequência é usado como o valor da sequência.
Aqui está um caso que vale a pena chamar a atenção. Se o tipo de construtor for acidentalmente deixado do lado direito do sinal de igual, o lado direito agora conterá quatro expressões, separadas por três vírgulas.
// 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);
O operador de vírgula avalia uma expressão da esquerda para a direita. Isso reduz o lado direito para:
float4 x = 1;
O HLSL usa a promoção escalar nesse caso, portanto, o resultado é como se isso tivesse sido escrito da seguinte maneira:
float4 x = float4(1,1,1,1);
Neste caso, deixar de fora o tipo float4 do lado direito provavelmente é um erro que o compilador não consegue detectar porque essa é uma instrução válida.
Operadores de comparação
Os operadores de comparação são: <, >, ==, !=, <=, >=.
Compare valores maiores que (ou menores que) qualquer valor escalar:
if( dot(lightDirection, normalVector) > 0 )
// Do something; the face is lit
if( dot(lightDirection, normalVector) < 0 )
// Do nothing; the face is backwards
Ou compare valores iguais a (ou não iguais a) qualquer valor escalar:
if(color.a == 0)
// Skip processing because the face is invisible
if(color.a != 0)
// Blend two colors together using the alpha value
Ou combine ambos e compare valores maiores ou iguais a (ou menor que ou igual a) qualquer valor escalar:
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
Cada uma dessas comparações pode ser feita com qualquer tipo de dados escalar.
Para usar operadores de comparação com tipos de vetor e matriz, use o todos os ou qualquer função intrínseca.
Essa operação falha porque a instrução if requer um único bool, mas recebe um bool4:
if (A4 < B4)
Essas operações são bem-sucedidas:
if ( any(A4 < B4) )
if ( all(A4 < B4) )
Operadores de prefixo ou postfixo
Os operadores de prefixo e postfix são: ++, --. Os operadores de prefixo alteram o conteúdo da variável antes que a expressão seja avaliada. Os operadores de postfixo alteram o conteúdo da variável depois que a expressão é avaliada.
Nesse caso, um loop usa o conteúdo de i para acompanhar a contagem de loops.
float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };
for (int i = 0; i<4; )
{
arrayOfFloats[i++] *= 2;
}
Como o operador de incremento de postfix (++) é usado, arrayOfFloats[i] é multiplicado por 2 antes de ser incrementado. Isso pode ser ligeiramente reorganizado para usar o operador de incremento de prefixo. Este é mais difícil de ler, embora ambos os exemplos sejam equivalentes.
float4 arrayOfFloats[4] = { 1.0f, 2.0f, 3.0f, 4.4f };
for (int i = 0; i<4; )
{
arrayOfFloats[++i - 1] *= 2;
}
Como o operador de prefixo (++) é usado, arrayOfFloats[i+1 - 1] é multiplicado por 2 após o incremento.
O decremento de prefixo e o operador de decremento de postfix (--) são aplicados na mesma sequência que o operador de incremento. A diferença é que o decremento subtrai 1 em vez de adicionar 1.
Operador de estrutura
O operador de seleção de membro da estrutura (.) é um período. Dada essa estrutura:
struct position
{
float4 x;
float4 y;
float4 z;
};
Ele pode ser lido da seguinte maneira:
struct position pos = { 1,2,3 };
float 1D_Float = pos.x
1D_Float = pos.y
Cada membro pode ser lido ou gravado com o operador de estrutura:
struct position pos = { 1,2,3 };
pos.x = 2.0f;
pos.z = 1.0f; // z = 1.0f
pos.z = pos.x // z = 2.0f
Operadores unários
Os operadores unários são: , -, +
Operadores unários operam em um único operando.
bool b = false;
bool b2 = !b; // b2 = true
int i = 2;
int i2 = -i; // i2 = -2
int j = +i2; // j = +2
Precedência do operador
Quando uma expressão contém mais de um operador, a precedência do operador determina a ordem de avaliação. A precedência do operador para HLSL segue a mesma precedência que C.
Observações
Chaves ({,}) iniciam e terminam um bloco de instrução. Quando um bloco de instrução usa uma única instrução, as chaves são opcionais.
Tópicos relacionados
-
instruções (DirectX HLSL)