Следующий пример является прямым потомком предыдущего в проекте из подкаталога Ех71 площадка с тенью вращается вокруг системы объектов, как будто источник света также перемещается в пространстве (рис 4.45).
Обратите внимание, что в отличие от предыдущего примера объекты сцены окрашены в разные цвета. Чтобы этого не произошло с тенями объектов и они остались бы серыми, процедуру воспроизведения сцены я снабдил параметром, задающим, включать ли источник света и надо ли использовать цвета:
procedure DrawScene (light : Boolean);
begin
glPushMatrix;
If light then begin
glEnable (GL_LIGHTING);
glEnable (GL_LIGHTO);
glColor3f(l, 0.3, 0.5);
end;
glutsolidTorus(0.1, 0.2, 16, 16);
If light then glColorSf(0.5, 0.8, 0.8);
glTranslatef(0.05, 0.08,-0.2);
glutSolidSphere(0.05, 16, 16);
glTranslatef(0.2, 0.2, 0.4);
glutsolidSphere(0.1, 16, 16);
glTranslatef(0.3, 0.3, -0.2);
If light then begin glDisable (GL_LIGHTO);
glDisable (GL_LIGHTING);
end;
glPopMatrix;
end;
При воспроизведении кадра нет никаких хитрых перемножений матриц, система координат ложной сцены перемещается вслед за площадкой и производится масштабирование:
procedure TfrmGL.WMPaint(var Msg: TWMPaint);
var
ps : TPaintStruct;
begin
BeginPaint(Handle, ps);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glPushMatrix;
glPushMatrix; // пол
glColor3f(0.8, 0.8, 1) ;
glRotatef(Angle, 0, 1, 0) ;
glBegin(GL_POLYGON);
glVertex3f(0.5, -0.5, 0.5);
glVertex3f(0.5, 0.5, 0.5);
glVertexSf(0.5, 0.5, -0.5);
glVertex3f(0.5, -0.5, -0.5);
glEnd;
glPopMatrix; glPushMatrix; // тень
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glColor4f(0, 0, 0, 0.4);
glTranslatef(0.5*c, 0, 0.5*a); // перемещение для тени
glScaled(abs(a),1,abs(с)); // отобразить изменения в расстоянии
glDisable(GL_DEPTH_TEST);
glRotatef(AngleSystem, 1, 1, 1) ;
DrawScene (False);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glPopMatrix;
glRotatef(AngleSystem, 1, 1, 1); // собственно система объектов
DrawScene (True);
glPopMatrix; SwapBuffers(DC); EndPaint(Handle, ps);
Angle := Angle +5; // угол поворота площадки
If Angle >= 360.0 then Angle := 0.0;
AngleSystem := AngleSystem + 2.5; // угол поворота системы объектов
If AngleSystem >= 360.0 then AngleSystem := 0.0;
a := -sin(Angle * Pi/180);
b := 0;
с := cos(Angle * Pi/180);
InvalidateRect(Handle, nil, False); // зацикливаем программу
end;
Замечание
Обратите внимание, что в обоих примерах тень рисуется всегда, даже тогда, когда выходит за границы пола.
Переходим к проекту из подкаталога Ех72, очень интересному примеру, результат работы которого представлен на Рисунок 4.46.