|
Июн
17
|
Вообще-то, квадраты в OpenGL ES примитивами не являются, но работать с ними крайне удобно, а визуализировать — ничуть не сложнее треугольника. В этом уроке, взяв за основу код треугольника, мы превратим его в квадрат. Визуализацию опять будем выполнять статичную, но вплотную подберемся к трансформациям (т.е. перемещению). Само собой, позже квадрат можно будет превратить в куб, а потом и в куб с текстурами.
Краткий обзор прошлого урока и введение в следующий
На прошлом уроке, оттолкнувшись от «чистого холста» в виде проекта Xcode мы получили белый треугольник с заливкой. Для этого мы создали массив вершин, с помощью “glVertexPointer()” сообщили OpenGL о данных и их формате, активировали готовность к визуализации массива вершин и выполнили собственно рендеринг с помощью “glDrawArrays()“.
На сей раз, взяв этот код за основу, мы сделаем из треугольника квадрат. Для этого достаточно будет отредактировать пару строк кода. Во-первых, как все, наверное, уже догадались, количество точек с 3 нужно изменить на 4. Изменится и способ рисования, о чем и сообщим OpenGL через “glDrawArrays()“.
Приступим.
Назначение вершин квадрата
Откройте проект Xcode из предыдущего урока и перейдите к методу “drawView“. Откомментируйте константу “triangleVertices[]” — избавляться от нее не стоит, поскольку она пригодится при трансформациях — и добавьте приведенный ниже код:
1 2 3 4 5 6 | const GLfloat squareVertices[] = { -1.0, 1.0, -6.0, // Верхний левый угол -1.0, -1.0, -6.0, // Нижний левый 1.0, -1.0, -6.0, // Верхний правый 1.0, 1.0, -6.0 // Нижний правый }; |
Мы описали квадрат. Обратили внимание на перечисление вершин в направлении против часовой стрелки?
Теперь откомментируйте код рисования для треугольника (оставим его тоже — позже пригодится), а именно три запроса к функциям “glVertexArray()“, “glEnableClientState()” и “glDrawArrays()” и добавьте представленный ниже фрагмент:
1 2 3 | glVertexPointer(3, GL_FLOAT, 0, squareVertices); glEnableClientState(GL_VERTEX_ARRAY); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
Три функции остались теми же, но в слегка отредактированном виде.
1 | glVertexPointer(3, GL_FLOAT, 0, squareVertices); |
Единственное изменение в том, что мы задаем для OpenGL другой комплект вершин — не для треугольника, а для квадрата.
Метод “glEnableClientState()” остается тем же самым, поскольку при рисовании OpenGL будет работать с массивом вершин (а не с массивом цветов или чего-то еще).
1 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
А вот здесь изменения существеннее. В предыдущем уроке в качестве первого параметра мы использовали “GL_TRIANGLES“, а третьим сделали 3. Если помните, второй параметр представляет собой смещение от начала массива. Он опять установлен на 0, поскольку наш массив вершин содержит исключительно вершины квадрата.
Первый аргумент — режим рисования. Теперь вы знакомы уже с двумя режимами рисования для OpenGL. На этом моменте сейчас остановимся поподробнее. Итак, доступные режимы рисования:
GL_POINTS
GL_LINES
GL_LINE_LOOP
GL_LINE_STRIP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
Точки и линии мы пока не обсуждали, поэтому рассмотрим три последних способа, относящихся к треугольникам. Сразу хочу напомнить, что массив вершин может включать не только треугольник: вариант с одним объектом в массиве — не предел.
GL_TRIANGLES: передача данного параметра означает, что OpenGL обрабатывает массив комплектами по 3 вершины. То есть, из первых трех создается треугольник, привязанный к вершине 1, вершине 2 и вершине 3. После этого программа переходит к обработке трех следующих вершин и так далее до конца массива.
GL_TRIANGLE_STRIP: OpenGL начинает с двух первых вершин, потом выстраивает треугольник, основываясь на каждой последующей и двух первых. Т.е. для “squareVertices[6~8]” треугольник формируется из “squareVerticies[0~2]” и “squareVerticies[3~5]“. Для “squareVertices[9~11]” треугольник формируется из “squareVertices[3~5]” и “squareVertices[6~8]” и т. д. до конца массива.
Примечание: ссылка на “squareVertices[0~2]” относится к:
squareVertices[0] — координата X
squareVertices[1] — координата Y
squareVertices[2] — координата Z
Если пока непонятно, не волнуйтесь — к этому моменту мы еще вернемся позже.
GL_TRIANGLE_FAN: после двух первых вершин для каждой последующей OpenGL формирует треугольник из предыдущей и первой вершины. То есть, для “squareVertices[6~8]” треугольник выстраивается из “squareVertices[3~5]” (предыдущая вершина) и “squareVertices[0~2]” (первая вершина).
Поскольку мы использовали “GL_TRIANGLES_FAN“, то на экране получим квадрат. Кнопка “Build & Go” выдаст долгожданный белый результат:

Вернитесь и взгляните на массив вершин. Постарайтесь представить, как треугольниками рисуется квадрат. OpenGL визуализирует это следующим образом:
Triangle Point 1: squareVertices[0~2] — Верхний левый угол квадрата
Triangle Point 2: squareVertices[3~5] — Нижний левый угол квадрата
Triangle Point 3: squareVertices[6~8] — Нижний правый угол квадрата
Итак, OpenGL рисует треугольник, который составит нижнюю левую половину квадрата. Представьте квадрат, поделенный надвое по диагонали линией из верхнего левого угла к правому нижнему. Увидели два треугольника? Нижний левый как раз и нарисовал OpenGL.
Примечание: ссылка на “squareVertices[0~2]” относится к:
squareVertices[0] — координата X
squareVertices[1] — координата Y
squareVertices[2] — координата Z
Точка треугольника 1: squareVertices[9~11] — Верхняя правая вершина квадрата
Точка треугольника 2: squareVertices[6~8] — Предыдущая вершина, нижняя правая
Точка треугольника 3: squareVertices[0~2] — Первая вершина, верхняя левая
Воспользовавшись всего одной новой точкой, программа визуализирует треугольник, завершая квадрат.
GL_TRIANGLE_STRIP
Вернитесь к коду и измените первый параметр в “glDrawArrays()” с “GL_TRIANGLE_FAN” на “GL_TRIANGLE_STRIP“:
1 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
Нажав кнопку “Build & Go“, получим следующее изображение:
Давайте разберемся, почему замена метода рисования не позволила получить квадрат. OpenGL обрабатывает массив вершин следующим образом:
Точка треугольника 1: squareVertices[0~2] — нижняя левая
Точка треугольника 2: squareVertices[3~5] — верхняя левая
Точка треугольника 3: squareVertices[6~8] — нижняя правая
Теперь OpenGL визуализирует треугольник, ориентируясь на первые три точки, т.е. обрабатывая нижнюю левую половину квадрата, как в предыдущем примере.
Точка треугольника 1: squareVertices[9~11] — верхняя правая
Точка треугольника 2: squareVertices[6~8] — Предыдущая вершина, нижняя правая
Точка треугольника 3: squareVertices[3~5] — 2-я предыдущая, нижняя левая
В итоге OpenGL визуализирует треугольник по трем этим точкам. В данном примере он получился повернутым на 90º от нужного нам положения.
Если упорядочить массив по-другому, то и метод “GL_TRIANGLE_STRIP” даст такой же квадрат, как “GL_TRIANGLE_FAN“. Помните, что массив вершин и метод рисования необходимо согласовывать, иначе результаты будут такими же непредсказуемыми, как при смене “FAN” на “STRIP“. Надеюсь, все запомнили, что нарисовать квадрат можно и с помощью “GL_TRIANGLE_STRIP” — достаточно лишь перекомпоновать массив:
1 2 3 4 5 6 | const GLfloat stripSquare[] = { -1.0, -1.0, -6.0, // нижняя левая 1.0, -1.0, -6.0, // нижняя правая -1.0, 1.0, -6.0, // верхняя левая 1.0, 1.0, -6.0 // верхняя правая }; |
В данном случае первый треугольник формируется из трех первых вершин, давая следующий результат:

подпись на фото: вершина формируется соединением третьей вершины со второй предыдущей вершиной
Теперь, указав точку для верхней правой вершины (P4), формируем новый треугольник с верхней левой (Р3) и второй предыдущей вершиной (Р2) в качестве нижней правой. На рис. ниже новые вершины показаны оранжевым, зеленым и красным цветами.

В результате перед нами снова квадрат. Надеюсь, это поможет не запомнить, что способ рисования всегда нужно согласовывать с представлением вершин.
И последнее…
Мы уже познакомились с треугольниками и квадратами — остались точки и линии. Оба этих вида примитивов мы рассмотрим в следующем уроке плюс, базируясь на том, что уже узнали, добавим немного цвета.
Научившись раскрашивать объекты, будем переходить к трехмерным текстурам. Doom 3 не обещаю, но самостоятельно создавать трехмерные объекты научу.

(6 голосов, средний: 4.83 из 5)
Последние комментарии
Всем ! Заходите на Фан-Футбол...
Windows Phone MarketPlace -...
Планируем приобрести дробемет и...
Как добавить в...
currentTitle = [[NSMutableString alloc] init];...