2012-10-23 14 views
5

mio vertex shader è,Problema con glBindBufferRange() OpenGL 3.1

uniform Block1{ vec4 offset_x1; vec4 offset_x2;}block1; 

out float value; 

in vec4 position; 

void main() 
{ 
    value = block1.offset_x1.x + block1.offset_x2.x;    

    gl_Position = position; 
} 

Il codice che sto usando per passare i valori è:

GLfloat color_values[8];// contains valid values 

glGenBuffers(1,&buffer_object); 

glBindBuffer(GL_UNIFORM_BUFFER,buffer_object); 

glBufferData(GL_UNIFORM_BUFFER,sizeof(color_values),color_values,GL_STATIC_DRAW); 

glUniformBlockBinding(psId,blockIndex,0); 

glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,0,16);            

glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,16,16); 

Ecco quello che mi aspetto è, a passare 16 byte per ogni uniforme vec4. Ottengo GL_INVALID_VALUE errore per offset = 16, dimensione = 16. Sono confuso con il valore di offset. Spec afferma che è corrispondente a "buffer_object".

risposta

8

C'è un alignment restriction per UBO quando si esegue il binding. L'offset di qualsiasi glBindBufferRange/Base deve essere un multiplo di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. Questo allineamento potrebbe essere qualsiasi cosa, quindi devi interrogarlo prima di costruire l'array di buffer uniformi. Ciò significa che non puoi farlo direttamente in logica C++ in fase di compilazione; deve essere una logica di runtime.

A proposito di query su cose in fase di esecuzione, il tuo codice è orribilmente rotto in molti altri modi. Non hai definito un qualificatore di layout per il tuo blocco uniforme; pertanto, viene utilizzato il valore predefinito: shared. E tu non puoi usare il layout `shared * senza querying the layout of each block's members from OpenGL.Ever.

Se aveste fatto una query, si sarebbe rapidamente scoperto che il blocco uniforme è di almeno 32 byte in termini di dimensioni, non 16. E dal momento che hai fornito solo 16 byte nella tua fascia, comportamento non definito (che include il possibilità di terminazione del programma) risultati.

Se si desidera essere in grado di definire oggetti C/C++ che corrispondono esattamente alla definizione di blocco uniforme, è necessario utilizzare il layout std140 e seguire le regole del layout di std140 nell'oggetto C/C++.

+0

Grazie mille per la risposta! Non ero a conoscenza di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. Avevo già interrogato il mio Uniform Block per le sue dimensioni (32 byte), ma ho pensato specificando 16 byte che potevo fornire i dati per il secondo componente "vec4" di Uniform Block, che presumo sia sbagliato. Penso che dovrei trattare il secondo componente "vec4" come un'uniforme individuale. Solo per aggiungere informazioni, se il layout non è std140 allora l'offset deve essere un multiplo di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. Di conseguenza, anche il buffer associato deve essere un multiplo di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT nella dimensione. – maverick9888

+0

cont. - Di conseguenza, anche il buffer associato deve essere un multiplo di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT di dimensioni, a condizione che si utilizzi un singolo oggetto buffer per fornire dati a più blocchi uniformi. – maverick9888

+0

"* se il layout non è std140, l'offset deve essere un multiplo di GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. *" No; l'offset * sempre * deve essere un multiplo di quello. Il layout 'std140' significa semplicemente che non devi interrogare la dimensione del buffer o l'offset delle singole uniformi, perché puoi calcolarle direttamente. Il buffer può essere di qualsiasi dimensione, ma quando si associa un intervallo, l'offset deve essere un multiplo di tale allineamento. –