2011-02-09 4 views
5

Desidero implementare un visualizzatore di immagini che consenta a un utente di eseguire lo zoom e una panoramica uniforme.Utilizzare l'indice come coordinata in OpenGL

Ho già eseguito l'opengl in modalità immediata, ma ora è deprecato a favore di VBO. Tutti gli esempi di VBO posso trovare le coordinate XYZ di ogni punto.

Sospetto di dover conservare tutti i miei dati in VRAM per ottenere un framerate durante il pan che può essere chiamato "liscio", ma ho solo i dati Y (la variabile dipendente). X è una variabile indipendente che può essere calcolata dall'indice e Z è costante. Se devo memorizzare X e Z, i requisiti di memoria (sia la dimensione del buffer che il trasferimento CPU-> GPU) sono triplicati. E ho decine di milioni di punti di dati attraverso i quali l'utente può scorrere, quindi l'utilizzo della memoria sarà non banale.

Esiste qualche tecnica per disegnare un array di vertici 1D, in cui l'indice viene utilizzato come altra coordinata oppure memorizzare un array 1-D (probabilmente in una trama?) E utilizzare un programma shader per generare il XYZ? Ho l'impressione che ho bisogno di un semplice shader in ogni caso con il nuovo modello di pipeline senza caratteristiche fisse per implementare il ridimensionamento e la traduzione, quindi se potessi combinare la generazione di coordinate X e Z e il ridimensionamento/traduzione di Y che sarebbe ideale.

È possibile? Conosci qualche codice di esempio che fa questo? O puoi almeno darmi qualche pseudocodice che dica cosa GL deve chiamare in quale ordine?

Grazie!

EDIT: Per assicurarsi che questo sia chiaro, ecco il codice immediatamente modalità equivalente, e il codice matrice vertice:

// immediate 
glBegin(GL_LINE_STRIP); 
for(int i = 0; i < N; ++i) 
    glVertex2(i, y[i]); 
glEnd(); 

// vertex array 
struct { float x, y; } v[N]; 
for(int i = 0; i < N; ++i) { 
    v[i].x = i; 
    v[i].y = y[i]; 
} 
glVertexPointer(2, GL_FLOAT, 0, v); 
glDrawArrays(GL_LINE_STRIP, 0, N); 

nota che v[] è il doppio di y[].

risposta

4

Questo va perfettamente bene per OpenGL.

Vertex Buffer Objects (VBO) può memorizzare qualsiasi informazione desiderata in uno dei formati supportati da GL. È possibile riempire un VBO con una sola coordinata:

glGenBuffers(1, &buf_id); 
glBindBuffer(GL_ARRAY_BUFFER, buf_id); 
glBufferData(GL_ARRAY_BUFFER, N*sizeof(float), data_ptr, GL_STATIC_DRAW); 

e quindi associare il corretto formato dell'attributo vertice per un pareggio:

glBindBuffer(GL_ARRAY_BUFFER, buf_id); 
glEnableVertexAttribArray(0); // hard-coded here for the sake of example 
glVertexAttribPointer(0, 1, GL_FLOAT, false, 0, NULL); 

Per poter utilizzare l'avrete bisogno di un semplice programma di shader .Il vertex shader può apparire come:

#version 130 
in float at_coord_Y; 

void main() { 
    float coord_X = float(gl_VertexID); 
    gl_Position = vec4(coord_X,at_coord_Y,0.0,1.0); 
} 

Prima di collegare il programma di shader, si dovrebbe legare è at_coord_Y all'indice attributo che verrà utilizzato (= 0 nel mio codice):

glBindAttribLocation(program_id,0,"at_coord_Y"); 

In alternativa, si può chiedere il programma dopo il collegamento per l'indice a cui è stato assegnato automaticamente questo attributo e poi usarlo:

const int attrib_pos = glGetAttribLocation(program_id,"at_coord_Y"); 

Buona fortuna!

+0

Grazie. Immagino che non sia chiaro come OpenGL sappia che voglio "coord_X" per indicare l'indice del vertice. –

+0

@Ben Voigt: mi sono perso inizialmente, mi dispiace :) La risposta è ora riparata (usando gl_VertexID). – kvark

+0

Grazie, ora ha molto più senso. E potrei usare 'glDrawArrays' per renderlo in massa? Sto chiedendo perché [la pagina di manuale per 'glDrawArrays'] (http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml) dice" Se GL_VERTEX_ARRAY non è abilitato, non vengono generate primitive geometriche. " Non si applica nel mondo OpenGL 3 in cui le posizioni dei vertici sono generate dallo shader? –

0

Vuoi memorizzare dieci milioni di coordinate XY, in VRAM?

Vorrei suggerire di calcolare quelle coordinate sulla CPU e passarle alla pipeline dello shader come uniformi (poiché le coordinate sono fissate all'immagine panoramica).

Semplicità.

+0

Quando eseguo il pan, devo rimuovere alcuni segmenti di linea dal display che si spostava fuori dallo schermo, aggiungere alcuni che erano stati rivelati e compensare il resto con una costante. Aggiungere una costante a un paio di migliaia di coordinate è veloce sulla CPU, ma poi devo trasferire nuovamente tutti i dati nella GPU, e devo farlo su ogni frame mentre il panning sta avendo luogo. Ok, anche con 60 FPS questo non sarà un grosso pezzo della larghezza di banda PCIe, ma perché sprecarlo? La GPU può fare i conti con la stessa facilità se semplicemente gli mando il nuovo indice più a sinistra da disegnare e la nuova traduzione, e può farlo in parallelo. –

+0

Scusa, ma non riesco a capire il tuo approccio. La panoramica di un'immagine dovrebbe essere implementata traducendo il quad strutturato (più grande della finestra). Texture è (probabilmente) residente e l'unico dato è un offset X/Y per la traduzione del quad strutturato. È possibile utilizzare più quad per la visualizzazione di più immagini. – Luca