В программе описана пользовательская процедура для рисования тени с учетом того, что все грани куба параллельны координатным плоскостям. Тень рисуется в виде шести отдельных серых многоугольников, для каждой грани объекта:
procedure TfrmGL.Shadow;
// подсчет координат точки тени для одной вершины
procedure OneShadow (х, у, z, h : GLfloat; var x1, y1 : GLfloat);
begin
x1 := x * LightPosition [2] / (LightPosition [2] - (z + h) ) ;
If LightPosition [0] < x
then begin If x1 > 0 then x1 := LightPosition [0] + x1 end
else begin If x1 > 0 then x1 := LightPosition [0] - x1 end;
y1 := у * LightPosition [2] / (LightPosition [2] - (z + h));
If LightPosition [1] < у
then begin If y1 > 0 then y1 := LightPosition [1] + y1 end
else begin If y1 > 0 then yl := LightPosition [1] - y1 end;
If x1 < 0 then x1 := 0 else
If x1 > SquareLength then x1 := SquareLength;
If y1 < 0 then y1 := 0 else
If y1 > SquareLength then y1 := SquareLength;
end;
var
x1, y1, x2, y2, хЗ, уЗ, х4, y4 : GLfloat;
wrkx1, wrky1, wrkx2, wrky2, wrkx3, wrky3, wrkx4, wrky4 : GLfloat;
begin
OneShadow (cubeX + cubeL, cubeY + cubeH, cubeZ, cubeW, x1, y1);
OneShadow (cubeX, cubeY + cubeH, cubeZ, cubeW, x2, y2);
OneShadow (cubeX, cubeY, cubeZ, cubeW, хЗ, уЗ);
OneShadow (cubeX + cubeL, cubeY, cubeZ, cubeW, x4, y4);
// пол на уровне -1 по оси Z, тень рисуется над полом, -0.99 по оси Z
If cubeZ + cubeW >= 0 then begin
glBegin (GL_QUADS); // тень от верхней грани объекта
glVertex3f (x1, y1, -0.99);
glVertex3f (x2, y2, -0.99);
glVertex3f (хЗ, уЗ, -0.99);
glVertexSf (x4, y4, -0.99);
glEnd;
end;
If cubeZ >= 0 then begin wrkx1 := x1;
wrky1 := y1;
wrkx2 := x2;
wrky2 := y2;
wrkx3 := хЗ;
wrky3 := уЗ;
wrkx4 := х4;
wrky4 := у4;
OneShadow (cubeX + cubeL, cubeY + cubeH, cubeZ, 0, x1, y1) ;
OneShadow (cubeX, cubeY + cubeH, cubeZ, 0, x2, y2) ;
OneShadow (cubeX, cubeY, cubeZ, 0, хЗ, уЗ) ;
OneShadow (cubeX + cubeL, cubeY, cubeZ, 0, x4, y4) ;
glBegin (GL_QUADS);
glVertex3f (x1, y1, -0.99) // нижняя грань
glVertexSf (x2, y2, -0.99)
glVertexSf (хЗ, уЗ, -0.99)
glVertex3f (x4, y4, -0.99)
glVertex3f (wrkx2, wrky2, -0.99); // боковые грани
glVertex3f (x2, y2, -0.99)
glVertexSf (хЗ, уЗ, -0.99)
glVertex3f (wrkx3, wrky3, -0.99);
glVertex3f (wrkx1, wrky1, -0.99);
glVertex3f (wrkx4, wrky4, -0.99);
glVertexSf (x4, y4, -0.99);
glVertex3f (x1, y1, -0.99);
glVertexSf (wrkx1, wrky1, -0.99);
glVertex3f (x1, y1, -0.99);
glVertex3f (x2, y2, -0.99);
glVertexSf (wrkx2, wrky2, -0.99);
glVertexSf (wrkx3, wrky3, -0.99);
glVertexSf (хЗ, уЗ, -0.99);
glVertexSf (x4, y4, -0.99);
glVertexSf (wrkx4, wrky4, -0.99);
glEnd;
end;
end;
Этот пример не универсальный, край пола я намеренно убрал за грани:, экрана, чтобы скрыть ошибку, возникающую при приближении тени к этому краю.
Перейдем к следующему примеру, проекту из подкаталога Ех70, результат работы которого представлен на Рисунок 4.44.