2011-02-09 2 views
5

Я хочу реализовать средство просмотра времени, которое позволяет пользователю масштабировать и плавно панорамировать.Использовать индекс в качестве координаты в OpenGL

Раньше я делал немедленный режим opengl, но теперь он устарел в пользу VBOs. На всех примерах VBOs я могу найти координаты XYZ для хранения каждой точки.

Я подозреваю, что мне нужно сохранить все данные в VRAM, чтобы получить частоту кадров во время панорамирования, которую можно назвать «гладкой», но у меня есть только данные Y (зависимая переменная). X - независимая переменная, которая может быть вычислена из индекса, а Z - постоянной. Если мне нужно хранить X и Z, тогда мои требования к памяти (как размер буфера, так и передача блока CPU-> GPU) утроятся. И у меня есть десятки миллионов точек данных, через которые пользователь может панорамировать, поэтому использование памяти будет нетривиальным.

Есть ли какой-либо метод для рисования 1-D вершинного массива, где индекс используется в качестве другой координаты или хранения 1-мерного массива (возможно, в текстуре?) И использования шейдерной программы для генерации XYZ? У меня создается впечатление, что мне нужен простой шейдер в любом случае в рамках новой модели конвейера с фиксированной функциональностью, чтобы реализовать масштабирование и перевод, поэтому, если бы я мог объединить генерацию координат X и Z и масштабирование/перевод Y, которые были бы идеально.

Возможно ли это? Вы знаете какой-нибудь пример кода, который делает это? Или вы можете хотя бы дать мне псевдокод, говорящий, что GL выполняет вызов в каком порядке?

Спасибо!

EDIT: Для того, чтобы убедиться, что это ясно, вот эквивалентный код в непосредственном режиме, и код массива вершин:

// 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); 

отмечают, что v[] в два раза превышает размер y[].

ответ

4

Это отлично подходит для OpenGL.

Vertex Buffer Objects (VBO) может хранить любую необходимую информацию в одном из поддерживаемых форматов GL. Вы можете заполнить VBO только с одной координатой:

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

А затем связать правильный формат атрибут вершинных ничьих:

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

Для того, чтобы использовать его вам нужна простую программа шейдера ,Вершинный шейдер может выглядеть следующим образом:

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

Перед связывающая шейдерной программы, вы должны связать это at_coord_Y с индексом атрибута вы будете использовать (= 0 в моем коде):

glBindAttribLocation(program_id,0,"at_coord_Y"); 

В качестве альтернативы, вы можете попросить программу после соединения для индекса, к которому этот атрибут был автоматически назначен, а затем использовать его:

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

удачи!

+0

Спасибо. Я думаю, я не понимаю, как OpenGL знает, что я хочу, чтобы 'coord_X' означал индекс вершины. –

+0

@Ben Voigt: Я пропустил это изначально, извините :) Ответ теперь исправлен (с использованием gl_VertexID). – kvark

+0

Спасибо, теперь это намного больше. И я мог бы использовать 'glDrawArrays', чтобы сделать это en-masse? Я спрашиваю, потому что [manpage для 'glDrawArrays'] (http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml) говорит:« Если GL_VERTEX_ARRAY не включен, геометрические примитивы не генерируются. " Не распространяется ли это в мире OpenGL 3, где вершинные местоположения генерируются шейдером? –

0

Будете ли вы хранить десять миллионов координат XY в VRAM?

Я бы предложил вам вычислить эти координаты на процессоре и передать их в конвейер шейдеров как униформы (поскольку координаты зафиксированы на развернутом изображении).

Храните его простым.

+0

Когда я качаю, мне нужно удалить некоторые сегменты линии с экрана, которые сдвинулись за пределы экрана, добавить некоторые из них, которые были обнаружены, и компенсировать остальную часть константой. Добавление константы в пару тысяч координат происходит быстро на CPU, но затем мне нужно снова передать все данные на GPU, и я должен сделать это на каждом кадре, пока происходит панорамирование. Хорошо, даже при 60 FPS это не будет такой большой порцией пропускной способности PCIe, но зачем ее тратить? Графический процессор может выполнять математику так же легко, если я просто отправлю ему новый левый индекс, который будет нарисован, и новый перевод, и может сделать это параллельно. –

+0

Извините, но я не понимаю ваш подход. Панорамирование изображения должно быть реализовано путем перевода текстурного квадрата (больше, чем окна просмотра). Текстура (возможно) резидентна, и единственными данными является смещение X/Y для перевода текстурированного квадрата. Несколько фрагментов можно использовать для отображения нескольких изображений. – Luca

Смежные вопросы