2011-02-09 13 views
5

Quiero implementar un visor de series temporales que permite al usuario acercar y alternar sin problemas.Usar índice como coordenada en OpenGL

He hecho algunos opengl de modo inmediato antes, pero eso ahora está en desuso en favor de VBO. Todos los ejemplos de VBOs que puedo encontrar almacenan las coordenadas XYZ de cada uno de los puntos.

Sospecho que necesito conservar todos mis datos en VRAM para obtener una tasa de cuadros por segundo durante el pan que se puede llamar "suave", pero solo tengo datos Y (la variable dependiente). X es una variable independiente que puede calcularse a partir del índice, y Z es constante. Si tengo que almacenar X y Z, mis requisitos de memoria (tanto el tamaño del buffer como la CPU-> GPU bloquean la transferencia) se triplican. Y tengo decenas de millones de puntos de datos a través de los cuales el usuario puede desplazarse, por lo que el uso de la memoria no será trivial.

¿Hay alguna técnica para dibujar una matriz de vértice 1-D, donde se usa el índice como la otra coordenada, o almacenar una matriz 1-D (probablemente en una textura?) Y usar un programa de sombreado para generar la XYZ? Tengo la impresión de que necesito un sombreador simple de todos modos con el nuevo modelo de canalización de características fijas para implementar escalado y traducción, así que si pudiera combinar la generación de coordenadas X y Z y la escala/traducción de Y que sería ideal.

¿Esto es posible? ¿Conoces algún código de muestra que haga esto? ¿O puede al menos darme un pseudocódigo que diga a qué funciones GL llamar en qué orden?

Gracias!

EDIT: Para asegurarse de que esto está claro, aquí está el código en modo inmediato equivalente, y el código de serie de vértices:

// 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 que v[] es dos veces el tamaño de y[].

Respuesta

4

Eso está perfectamente bien para OpenGL.

Vertex Buffer Objects (VBO) puede almacenar cualquier información que desee en uno de los formatos admitidos GL. Puede llenar un VBO con sólo una sola coordenada:

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

Y a continuación, enlazar el formato adecuado atributo vértice de un empate:

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

Para utilizarlo se necesita un programa de sombreado sencillo .El vertex shader puede verse como:

#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); 
} 

Antes de vincular el programa de sombreado, que debe unir es at_coord_Y al índice de atributos que va a utilizar (= 0 en el código):

glBindAttribLocation(program_id,0,"at_coord_Y"); 

Alternativamente, Puede consultar el programa después de vincular el índice al cual se asignó este atributo automáticamente y luego usarlo:

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

¡Buena suerte!

+0

Gracias. Supongo que no estoy seguro de cómo OpenGL sabe que quiero que 'coord_X' signifique el índice del vértice. –

+0

@Ben Voigt: me lo perdí inicialmente, lo siento :) La respuesta está arreglada ahora (usando gl_VertexID). – kvark

+0

Gracias, eso tiene mucho más sentido ahora. Y podría usar 'glDrawArrays' para renderizar este en masa? Lo estoy preguntando porque [la página de manual para 'glDrawArrays'] (http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml) dice" Si GL_VERTEX_ARRAY no está habilitado, no se generan primitivas geométricas. " ¿Eso no se aplica en el mundo de OpenGL 3 donde el shader genera ubicaciones de vértices? –

0

¿Almacenaría diez millones de coordenadas XY, en VRAM?

Yo sugeriría que calcule esas coordenadas en la CPU, y las pase a la tubería del sombreador como uniformes (ya que las coordenadas se fijan a la imagen panoramizada).

Hazlo simple.

+0

Cuando desplace, necesito eliminar algunos segmentos de línea de la pantalla que se movió fuera de la pantalla, agregar algunos que fueron revelados y compensar el resto por una constante. Agregar una constante a un par de miles de coordenadas es rápido en la CPU, pero luego tengo que transferir todos los datos a la GPU nuevamente, y tengo que hacer esto en cada cuadro mientras se está realizando la panorámica. Ok, incluso a 60 FPS, esto no va a ser una gran parte del ancho de banda de PCIe, pero ¿para qué desperdiciarlo? La GPU puede hacer los cálculos con la misma facilidad si simplemente le envío el nuevo índice de la izquierda para dibujar y una nueva traducción, y puede hacerlo en paralelo. –

+0

Lo siento, pero no puedo entender su enfoque. La panoramización de una imagen debe implementarse traduciendo el cuadrante texturizado (más grande que la ventana gráfica). La textura es (probablemente) residente, y el único dato es un desplazamiento X/Y para traducir el cuadrante texturizado. Se podrían usar múltiples cuadrantes para mostrar múltiples imágenes. – Luca

Cuestiones relacionadas