Помогите мне настроить OpenGL для 2D - PullRequest
4 голосов
/ 06 февраля 2011

Я пишу свое первое 2D-приложение для Android с использованием OpenGL.Я пишу это на своем Desire, поэтому мои экранные координаты должны быть от 0,0 до 799 479 в альбомном режиме.Я пытаюсь заставить OpenGL использовать этот диапазон в мировых координатах.

Приложение, такое как оно, до сих пор работает нормально, но мне пришлось настроить цифры, чтобы на экране появилось что-то, и я разочарован неспособностью понять взаимосвязь междуматрица проекции и рендеринг текстур в этом отношении.

Установка матрицы проекции:

gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
float size = .01f * (float) Math.tan(Math.toRadians(45.0) / 2);             
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-size, size, -size / ratio, size / ratio, 0.01f, 100.0f);
//    GLU.gluOrtho2D(gl, 0,width, 0, height);

Я хочу понять, 0,01f и 100,0f здесь.Что я использую для описания 2D-мира 0,0 -> 799 479 с нулевым значением az?

Кроме того, я не уверен, что «лучше» - используя glFrustumF или GLU.gluOrtho2D. Последний имеетболее простые параметры - только размеры области просмотра - но я не получил ничего с этим.(Некоторые сайты имеют высоту и 0, но это не имеет значения.) Но разве это не должно быть естественным выбором для 2D-использования OpenGL?Нужно ли что-то указывать в OpenGL: «Я делаю это в 2D - пожалуйста, игнорируйте третье измерение везде, в интересах скорости»?

Рисование моих текстур:

Я рисую вещи, используя 2 текстурированных треугольника.Соответствующие части моего init (дайте мне знать, если мне нужно отредактировать свой вопрос с более подробной информацией):

gl.glMatrixMode(GL10.GL_MODELVIEW);                             
gl.glLoadIdentity();
gl.glTranslatex(nXpos, nYpos, nZoomin);         
gl.glRotatef(nRotZ, 0, 0, 1);               
gl.glScalef((float)nScaleup,(float)nScaleup, 0.0f);
...
...
gl.glVertexPointer(2, GL10.GL_FIXED, 0, mVertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);      


mVertexBuffer is an IntBuffer and contains:
int  vertices[] =  
{
    -1,   -1,
    1,  -1,
    -1, 1,
    1,  1   
};

Я не собираюсь, в конечном счете, переходить в nZoomin - ясделал это так, потому что именно так я нашел «магические числа», необходимые для того, чтобы что-то увидеть!В настоящее время мне нужно использовать -1000 там, с меньшими числами, получая меньшие изображенияПравильно ли я думаю, что должен быть какой-то способ иметь нулевое значение для nZoomin, когда матрица проекции установлена ​​правильно?

Мои текстуры в настоящее время имеют размер 128x128 (но могут иметь разные размеры, хотя, возможно, всегда квадратные).У меня нет возможности узнать, когда они отображаются в реальном размере в настоящее время.Я хотел бы иметь возможность передать значение, скажем, 128 для nScaleup, чтобы оно отображалось в реальном размере.Это связано с матрицей проекции или у меня есть две отдельные проблемы?

Ответы [ 2 ]

8 голосов
/ 06 февраля 2011

Если вы работаете в 2D, вам не нужно glFrustum, просто используйте glOrtho.Примерно так:

void glOrthof(0, 800, 0, 480, -1, 1);

Это поместит источник внизу слева.Если вы хотите, чтобы он находился в левом верхнем углу, используйте:

void glOrthof(0, 800, 480, 0, -1, 1);

Для 480 и 800 вам, очевидно, следует подставить фактический размер вашего представления, чтобы ваше приложение было переносимым на другие размеры экрана и конфигурации.

Я передаю -1 и 1 для диапазона z, но это не имеет большого значения, потому что ортогональная проекция помещает (x, y, z) в одно и то же место на экране, независимо от значенияиз з.(хотя ближний и дальний не должны быть равны.) Это единственный способ сказать OpenGL игнорировать координату z;особого режима «2D» не существует, ваши матрицы по-прежнему имеют размер 4x4, а 2-мерные вершины получат координату z, равную 0.

Обратите внимание, что ваши координаты не находятся в диапазоне от 0 до 799, но на самом деле от 0 до 800. Причина в том, что OpenGL интерпретирует координаты как лежащие между пикселями, а не на их.Думайте об этом как о линейке 30 см: на ней 30 интервалов по сантиметру, а отметки нумеруются от 0 до 30.

Используемый вами буфер вершин не работает, потому что вы 'используется формат GL_FIXED.Это означает 16 бит до десятичной точки и 16 бит после нее, поэтому, чтобы задать квадрат 2x2 вокруг начала координат, вам нужно умножить каждое значение на 0x10000:

int vertices[] =  
{
    -0x10000, -0x10000,
     0x10000, -0x10000,
    -0x10000,  0x10000,
     0x10000,  0x10000
};

Это, вероятно, причинапочему вам нужно так масштабировать его.Если вы используете этот массив без масштабирования, вы должны получить квадрат 2х2 пикселя.Превращение этого в квадрат 1x1, чтобы размер можно было контролировать напрямую с помощью масштабного коэффициента, оставлено читателю в качестве упражнения;)

1 голос
/ 06 февраля 2011

Должен ли я установить что-то, чтобы сказать OpenGL "Я делаю это в 2D

Мне кажется, проблема в том, что вы используете проекционную матрицу для перспективного проецирования. Вместо этого вы должны использовать параллельную проекцию. Чтобы получить эту матрицу, вы можете использовать функцию glOrtho () .

gl.glMatrixMode(GL10.GL_PROJECTION);
...
gl.glOrtho(0, width, 0, height, 0, 128);

Теперь значение z больше не влияет на размер объекта.


Я хочу понять, 0,01f и 100,0f здесь. Что я использую для описания 2D-мира 0,0 -> 799 479 со значением z, равным нулю?

Правильно, что в 2D-мире у вас нет реальных значений z. Но ты должен решить какой из ваших объектов вы хотите нарисовать сначала. Есть два способа решить это:

  1. Деактивировать GL_DEPTH_TEST и все отрисовывается в выбранном вами порядке
  2. Активируйте GL_DEPTH_TEST и позвольте OpenGL решить
...