Каждой вершине указывать цвет совсем не обязательно. Если вы хотите нарисовать треугольник одного цвета, то этот цвет указывается один раз – перед рисованием самого примитива.
Забегая вперёд, скажу, что плавного перетекания цветов как на рисунке может и не быть, если перед рисованием вызвать процедуру glShadeModel(GL_FLAT), по умолчанию её параметр – GL_SMOOTH. Эта процедура указывает, сглаживать или нет углы между смежными полигонами. Вот картинки для иллюстрации её действия:
Раз уж я сказал о штриховке линий, то нужно сказать и о трафарете – штриховке для полигонов. Он включается командой glEnable(GL_POLYGON_STIPPLE). Также как и с линиями, трафарет задаётся массивом, который определяет битовую маску. Размер трафарета - 32x32 бита, т.е. размер массива будет 128 байт.
Мне было лень прописывать каждый из 128 байт маски по отдельности, и я сформировал её в цикле, и вот результат:
С++ |
void TForm1::Draw() { glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT); // формируем маску for(int k=0;k<16;k++) for(int i=0;i<8;i++) stip[k][i]:=k-i; glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(@stip); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glColor3f(1,0,0); glBegin(GL_TRIANGLES); glVertex2f(0,2); glVertex2f(8,9); glVertex2f(10,4); glEnd(); SwapBuffers(ghDC); } |
Delphi |
procedure TForm1.Draw; var stip:array [1..16,1..8] of GLubyte; i,k:byte; begin glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT); // формируеммаскуfor k:=1 to 16 do for i:=1 to 8 do stip[k][i]:=k-i; glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(@stip); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glColor3f(1,0,0); glBegin(GL_TRIANGLES); glVertex2f(0,2); glVertex2f(8,9); glVertex2f(10,4); glEnd; SwapBuffers(ghDC); end; |
Вот результат:
Вообще маска формируется один раз, поэтому, если вы перенесёте код её формирования в другое место (например в FormCreate), то программа будет работать быстрее.
Ещё хотелось бы сказать о массивах OpenGL. Этот метод позволяет хранить все вершины объекта в массиве, причем в этом массиве можно хранить не только координаты вершин, но и их атрибуты (иногда это бывает полезно). Но товарищи из Borland’а решили, что нам это не нужно и не объявили соответствующие процедуры и константы. Без этого легко можно обойтись, но всё-таки обидноL.
Параллелепипед
Не знаю, заметили вы или нет, но GLU не позволяет создавать параллелепипеды. Давайте это исправим: напишем процедуру, рисующую параллелепипед.
С++ |
void piped(GLfloat a, GLfloat b, GLfloat c) { glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glBegin(GL_QUAD_STRIP); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2,-b/2, c/2); glVertex3f(-a/2, b/2,-c/2); glVertex3f(-a/2, b/2, c/2); glVertex3f( a/2, b/2,-c/2); glVertex3f( a/2, b/2, c/2); glVertex3f( a/2,-b/2,-c/2); glVertex3f( a/2,-b/2, c/2); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2,-b/2, c/2); glEnd(); glBegin(GL_QUADS); glVertex3f(-a/2,-b/2, c/2); glVertex3f(-a/2, b/2, c/2); glVertex3f( a/2, b/2, c/2); glVertex3f( a/2,-b/2, c/2); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2, b/2,-c/2); glVertex3f( a/2, b/2,-c/2); glVertex3f( a/2,-b/2,-c/2); glEnd(); } |
Delphi |
procedure piped(a,b,c:GLfloat); begin glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glBegin(GL_QUAD_STRIP); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2,-b/2, c/2); glVertex3f(-a/2, b/2,-c/2); glVertex3f(-a/2, b/2, c/2); glVertex3f( a/2, b/2,-c/2); glVertex3f( a/2, b/2, c/2); glVertex3f( a/2,-b/2,-c/2); glVertex3f( a/2,-b/2, c/2); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2,-b/2, c/2); glEnd; glBegin(GL_QUADS); glVertex3f(-a/2,-b/2, c/2); glVertex3f(-a/2, b/2, c/2); glVertex3f( a/2, b/2, c/2); glVertex3f( a/2,-b/2, c/2); glVertex3f(-a/2,-b/2,-c/2); glVertex3f(-a/2, b/2,-c/2); glVertex3f( a/2, b/2,-c/2); glVertex3f( a/2,-b/2,-c/2); glEnd; end; |
Можно проверять!
glOrtho вызовем также, как и в примере со сферой: glOrtho(-5,5, -5,5, 1,12).
А в Draw напишем следующее:
С++, Delphi |
glColor3f(0.6,0.7,0.9); glPushMatrix; glRotatef(10, 0,0,1); glRotatef(25, 0,1,0); glRotatef(20, 1,0,0); piped(5,1.2,3.5); glPopMatrix; |
И получим картинку: