Attributi vertice OpenGL - Normalizzazione


8

Purtroppo, ho cercato e non ho trovato una risposta definitiva.

Quando normalizzeresti i dati del vertice in OpenGL usando il seguente comando:

glVertexAttribPointer(index, size, type, normalize, stride, pointer);

Cioè quando sarebbe normalize == GL_TRUE; quali situazioni e perché dovresti scegliere di lasciare che la GPU esegua i calcoli invece di preelaborarla? Tutti gli esempi che io abbia mai visto, hanno impostato su GL_FALSE; e non riesco personalmente a vederne un uso. Ma i Khronos non sono stupidi, quindi deve essere lì per qualcosa di utile (e probabilmente comune).

Risposte:


9

Il parametro "normalizzato" influenza l'uso di valori in punti fissi.

Questo documento dice il parametro "Specifica se i valori dei dati a virgola fissa devono essere normalizzati (GL_TRUE) o convertiti direttamente come valori a virgola fissa (GL_FALSE) quando si accede".

Inoltre, questo indica "Per glVertexAttribPointer, se normalizzato è impostato su GL_TRUE, indica che i valori memorizzati in un formato intero devono essere mappati nell'intervallo [-1,1] (per valori con segno) o [0,1] ( per i valori senza segno) quando sono accessibili e convertiti in virgola mobile. In caso contrario, i valori verranno convertiti in float direttamente senza normalizzazione. "

In sintesi, se non si utilizzano valori in virgola fissa, non è necessario preoccuparsene. In tal caso, questo flag controlla se (ad esempio) il valore byte 128 deve essere 0,5 o 128,0.


3
Questo in realtà non risponde alla domanda, ho già capito cosa fa, ma volevo sapere quando sarebbe effettivamente applicabile a un'implementazione "comune".
Deceleratedcaviar

2
Sono abbastanza sicuro che era rilevante quando molte applicazioni mobili utilizzavano principalmente la matematica a virgola fissa e non volevano toccare la matematica a virgola mobile. Un'altra possibilità è che a volte potresti voler archiviare i dati in modo più compatto, diciamo, in byte, se la precisione è sufficiente, e lascia che OpenGL converta i byte nell'intervallo 0..1.
Jari Komppa,

È ancora rilevante. Pensa ad esempio ai raggi UV. Potresti non voler sprecare spazio e archiviarlo come float2, quindi lo memorizzi come 2 uint8 invece come un'ottimizzazione e imposti il ​​flag di normalizzazione in modo da ottenere l'intervallo [0, 1] anziché [0, 256] nel programma.
Vuoto il

128 diventerà 0,5 o 128/255 = leggermente più alto?
riv

11

Questa è una vecchia domanda, ma la risposta attuale non spiega davvero per cosa li useresti.

Si tratta di risparmiare spazio. E con gli attributi del vertice, meno spazio può significare prestazioni più elevate (se sei legato al trasferimento del vertice).

I colori in genere non richiedono molto più di 8 bit per componente. A volte hai bisogno di 16 bit, se si tratta di un valore di luce HDR o qualcosa del genere. Ma per le caratteristiche della superficie (che è ciò che la maggior parte degli attributi del vertice sono), 8 bit vanno bene. Quindi i byte normalizzati senza segno sono un buon formato di vertice.

Le coordinate delle trame non richiedono 32 bit di precisione in virgola mobile. È sufficiente un valore di 16 bit da [0, 1]. I cortometraggi non firmati così normalizzati sono un formato vertice ragionevole.

Le normali non hanno mai bisogno di 32 bit di precisione. Sono indicazioni. I byte normalizzati con segno a 8 bit tendono ad essere un po 'piccoli, ma i valori normalizzati a 10 bit sono abbastanza buoni per la maggior parte del tempo. OpenGL (3.3+) consente persino di utilizzare normali a 10 bit tramite un formato compresso 10/10/10/2 bit, memorizzato in un singolo numero intero senza segno a 32 bit.

Puoi persino giocare con posizioni di vertice, se ti trovi in ​​un serio bisogno di più memoria.

Senza la normalizzazione, dovresti sprecare preziosi cicli nei tuoi attributi di byte che dividono lo shader per 255.0. Perché farlo, quando l'hardware può farlo gratuitamente?


Una bella risposta Ma il sovraccarico della matematica in virgola mobile della divisione è paragonabile a una diminuzione delle dimensioni normali del 50%? (Vale a dire 32 bit per dire 16 bit); su hardware MODERNO. Soprattutto da allora, non abbiamo davvero bisogno di preoccuparci di troppa memoria (almeno nel mio caso).
Deceleratedcaviar

1
@Daniel: Beh, pensiamoci. Su "hardware MODERNO", l'overhead del passaggio di valori normalizzati è ... zero. Il sovraccarico di fare la divisione nello shader è ... diverso da zero. Non importa quanto sia minacciosamente piccolo, è ancora più grande di zero. Per non parlare dei risparmi sulla larghezza di banda dell'invio di un blocco a 32 byte di dati vertici anziché di un blocco a 64 byte. Oh, e lo shader non deve essere programmato appositamente; puoi usare lo stesso shader per prendere valori normalizzati o float. Se metti la divisione nello shader, ora hai bisogno di nuovi shader per diverse dimensioni di dati vertici.
Nicol Bolas,

Grazie per la bella risposta Lo terrò sicuramente a mente, al momento non è necessario poiché sto inviando dati di vertice allineati, ma quando aggiungo ulteriori informazioni potrebbe non essere lo stesso, e questo potrebbe essere un grande vantaggio, sia nella memorizzazione nella cache e throughput.
Deceleratedcaviar

Qualche strategia su come convertire il normale (attualmente memorizzato in una sequenza di (3x) float a 32 bit) in un int a 32 bit (10/10/10/2)?
Deceleratedcaviar

@Daniel: se stai chiedendo come utilizzare l' estensione ARB_vertex_type_2_10_10_10_rev , ti suggerisco di leggere le specifiche di estensione che ho appena collegato. Se stai chiedendo come eseguire personalmente la manipolazione dei bit, suggerirei una struttura in stile C che contenga campi di bit .
Nicol Bolas,

0

Immagina di avere una mesh con normali di alta precisione e un'altra mesh con bassa. Con la normalizzazione degli attributi è possibile utilizzare lo stesso shader ma racchiudere i normali della seconda mesh in byte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.