OpenGL в Delphi

При изменении размеров окна программы получается очень интересный эффект




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

Procedure TfrmGL. FormResize(Sender: TObject);
begin
glViewport(0, 0, ClientWidth, ClientHeight);
glClear(GL_STENCIL_BUFFER_BIT); // очищаем буфер трафарета
glMatrixMode(GL_PROJECTION);
glLoadldentity;
g!0rtho(-3.0, 3.0, -3.0, 3.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadldentity;
// создаем квадрат посередине сцены
glStencilFunc (GL_ALWAYS, $1, $1);
glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
glBegin(GL_QUADS);
glVertex3f (-1.0, 0.0, 0.0);
glVertex3f (0.0, 1.0, 0.0);
glVertex3f (1.0, 0.0, 0.0);
glVertex3f (0.0, -1.0, 0.0);
glEnd;
// переопределяем видовые параметры
glMatrixMode(GL_PROJECTION);
glLoadldentity;
gluPerspective(45.0, ClientWidth / ClientHeight, 3.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadldentity;
glTranslatef(0.0, 0.0, -5.0);
InvalidateRect(Handle, nil, False);
end;

Видовые параметры переопределяются по ходу обработки события. Вы можете вставить showMessage в этот обработчик, чтобы создать паузу и увидеть, как заданы видовые параметры в первом и во втором случаях. Квадрат строится в "мировой" системе координат, затем видовые параметры берут за основу размеры экрана. Поэтому при изменениях размера окна торы не меняют пропорций, а квадрат принимает форму ромба.

Замечание
Обращаю ваше внимание на то, что квадрат "рисуется" не в буфере кадра, т е на экране, а в буфере трафарета.

Теперь перейдем к собственно воспроизведению:

// рисуем синюю сферу там, где значение буфера трафарета равно 1
glStencilFunc (GLJ2QUAL, $1, $1);
glCallList (BLUEMAT);
glutSolidSphere (0.5, 20, 20);
// рисуем желтые торы там, где значение буфера трафарета не равно 1
glStencilFunc (GL_NOTEQUAL, $1, $1);
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
glPushMatrix;
glRotatef (45.0, 0.0, 0.0, 1.0);
glRotatef (45.0, 0.0, 1.0, 0.0);
glCallList (YELLOWMAT);
glutSolidTorus (0.275, 0.85, 20, 20);
glPushMatrix;
glRotatef (90.0, 1.0, 0.0, 0.0);
glutSolidTorus (0.275, 0.85, 20, 20);
glPopMatrix;
glPopMatrix;

Поскольку параметры glstencilop не изменились перед воспроизведением синей сферы, рисуются все ее участки, но в области, пересекающейся с вырезанным квадратом, мы видим лицевую сторону сферы, а в остальных ее участках рисуется задняя поверхность. Пример простой, но очень изящный, рекомендую вам разобраться в нем основательно.
Рисунок 4.25 иллюстрирует работу следующего, тоже весьма интересного примера, проекта из подкаталога Ех37.



Содержание раздела