Задание
Необходимо написать программу, в которой реализуются описанные выше специальные эффекты. Пример того, что должно получиться, — программа lab4api. Исходный код не приводится потому, что в таком случае вам просто нужно было бы заменить функции рисования тора и октаэдра на ваши фигуры.
Как и в лабораторной работе № 3, вам нужно создать сцену с двумя перемещающимися в пространстве фигурами (теми же, что и в 3-й лаб. работе). Только теперь вместо двух прожекторов у вас один точечный источник света. Предоставлять возможность в программе интерактивно менять параметры источников света и камеры нет необходимости. Для того, чтобы тень рисовалась на четырех стенах, а не только на одной, необходимо отдельно рисовать тень на каждой стене. При этом нужно активизировать дополнительные отсекающие плоскости (функции glClipPlane, glEnable(GL_CLIP_PLANE0), …), чтобы рисование тени производилось в пределах стены.
В работе следует использовать только перспективную проекцию.
В целом, последовательность рисования может быть следующей.
1. Нарисовать отраженную от левой стены сцену.
2. Нарисовать прозрачную левую стену.
3. Нарисовать отраженную от правой стены сцену.
4. Нарисовать прозрачную правую стену.
5. Нарисовать оставшуюся стену, пол и потолок.
6. Нарисовать тени последовательно на каждой из трех стен и на полу.
7. Нарисовать обычный вид сцены (две фигуры).
8. Нарисовать источник света.
Для рисования отраженных сцен нужно изменить положение источника света и произвести необходимую трансляцию системы координат, после чего задать масштабирование в виде
1 |
glScalef(-1.0f, 1.0f, 1.0f); |
Порядок обхода нужно заменить на «по часовой стрелке». Прозрачные стены нужно рисовать при выключенном освещении. Из-за этого, правда, сцена теряет реалистичность. Плюс тому, кто сможет придумать выход из положения. Источник света (то есть окружающая его сфера) тоже рисуется при выключенном освещении. В каталоге Common содержатся заголовочные файлы и исходные тексты, в том числе для использования библиотеки glTools. Файл glext.h позволяет использовать функции OpenGL версий 1.2 и более.
Заголовочные файлы от Microsoft содержат описание функций OpenGL 1.1. Таким образом, вы можете использовать заголовочный файл OpenGLSB.h вместо glut.h.
Чтобы использовать функцию gltMakeShadowMatrix, включите в состав своего проекта файлы MatrixMath.c и VectorMath.c. Добавьте заголовочный файл GLTools.h. Не забудьте для файлов *.c задать свойство (Properties) С/C++—>Advanced—>Compile As – Compile as C++ code (/TP).
Также нужно будет в свойствах проекта указать, что не нужно использовать Precompiled Headers.
Текст функции прорисовки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
void RenderScene(void) { float xRot2=xRot,yRot2=yRot; // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); int Situation=0; while (Situation<=2) { glPushMatrix(); // Draw the ground, we do manual shading to a darker green // in the background to give the illusion of depth // Now rotate the jet around in the new flattend space glRotatef(xRot2, 1.0f, 0.0f, 0.0f); glRotatef(yRot2, 0.0f, 1.0f, 0.0f); glDisable(GL_CLIP_PLANE0); glDisable(GL_CLIP_PLANE1); glDisable(GL_CLIP_PLANE2); glDisable(GL_CLIP_PLANE3); glDisable(GL_CLIP_PLANE4); switch (Situation) { case 0: glBegin(GL_QUADS); glColor4f(0.5f,0.5f,1.0f,0.9f); glNormal3f(1.0f,0.0f,0.0f); glVertex3f(-SX,SY,SZ); glVertex3f(-SX,-SY,SZ); glVertex3f(-SX,-SY,-SZ); glVertex3f(-SX,SY,-SZ); /*glNormal3f(-1.0f,0.0f,0.0f); glVertex3f(SX,SY,-SZ); glVertex3f(SX,-SY,-SZ); glVertex3f(SX,-SY,SZ); glVertex3f(SX,SY,SZ);*/ glScalef(-1.0f,0.0f,0.0f); glEnd(); glTranslatef(-SX*2,0.0f,0.0f); k=130; break; case 1: glScalef(-1.0f,0.0f,0.0f); glTranslatef(SX*2,0.0f,0.0f); k=130; break; case 2: k=0; break; } glEnable(GL_LIGHTING); const float SM=0.1f; const float SX2=SX+SM,SY2=SY+SM,SZ2=SZ+SM; CPoint kub[8] = {{-SX2,-SY2,-SZ2},{-SX2,-SY2, SZ2},{SX2,-SY2,SZ2},{SX2,-SY2,-SZ2,},{-SX2,SY2,-SZ2},{-SX2,SY2, SZ2},{SX2,SY2,SZ2},{SX2,SY2,-SZ2,}}; //координаты точек куба /*CPoint kub2[8] = {{-1,-1,-1},{-1,-1, 1},{1,-1,1},{40,-40,-40,},{-40,40,-40},{-40,40, 40},{40,40,40},{40,40,-40,}}; glClearColor(0.0,0.0,0.0,1.0); //установка цвета экрана glPolygonMode(GL_FRONT_AND_BACK, Gradient); glEnable(GL_COLOR_MATERIAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); GLfloat atmoColor[4] = {0.8, 0.8, 1.0, 0.005}; glFogfv (GL_FOG_COLOR, atmoColor); //glFogf (GL_FOG_START, 0.5); //glFogf (GL_FOG_END, 0.5); glFogf (GL_FOG_DENSITY, 0.005); glEnable(GL_FOG); //---------------------------------------------------------------------------// GLTVector3 points_w1[3] = {{-40,40,40},{-40,-40,40},{-40,40, -40}}; GLTVector3 points_w2[3] = {{40,40,-40},{-40,40, -40},{40,-40,-40}}; GLTVector3 points_w3[3] = {{40,40,40},{40,40,-40},{40,-40,40}}; GLTVector3 points_f[3] = {{-40,-40,-40},{-40,-40, 40},{40,-40,40}}; GLfloat lightPos_f[] = {0.0, 38.0,0.0,1.0}; //---------------------------------------------------------------------------//*/ GLdouble coeffic_f[4] = {0.0,0.0,0.0,0.0}; GLdouble coeffic_w1[4] = {0.0,0.0,0.0,0.0}; GLdouble coeffic_w2[4] = {0.0,0.0,0.0,0.0}; GLdouble coeffic_w3[4] = {0.0,0.0,0.0,0.0}; GLdouble coeffic_w4[4] = {0.0,0.0,0.0,0.0}; PlaneParam(0,1,2,coeffic_f,kub); PlaneParam(4,5,1,coeffic_w1,kub); PlaneParam(7,4,0,coeffic_w2,kub); PlaneParam(2,6,7,coeffic_w3,kub); PlaneParam(1,5,6,coeffic_w4,kub); glClipPlane(GL_CLIP_PLANE0,coeffic_f); glClipPlane(GL_CLIP_PLANE1,coeffic_w1); glClipPlane(GL_CLIP_PLANE2,coeffic_w2); glClipPlane(GL_CLIP_PLANE3,coeffic_w3); glClipPlane(GL_CLIP_PLANE4,coeffic_w4); glEnable(GL_CLIP_PLANE0); glEnable(GL_CLIP_PLANE1); glEnable(GL_CLIP_PLANE2); glEnable(GL_CLIP_PLANE3); glEnable(GL_CLIP_PLANE4); glDisable(GL_DEPTH_TEST); glBegin(GL_QUADS); glColor3ub(0,255,k); glNormal3f(0.0f,1.0f,0.0f); glVertex3f(SX, -SY, -SZ); glVertex3f(-SX, -SY, -SZ); glColor3ub(0,255,k); glVertex3f(-SX, -SY, SZ); glVertex3f(SX, -SY, SZ); glNormal3f(0.0f,-1.0f,0.0f); glColor3ub(0,255,k); glVertex3f(SX, SY, SZ); glVertex3f(-SX, SY, SZ); glColor3ub(0,255,k); glVertex3f(-SX, SY, -SZ); glVertex3f(SX, SY, -SZ); ////////////////////////////// //glColor3ub(k,132,k); glNormal3f(0.0f,0.0f,1.0f); glVertex3f(-SX,SY,-SZ); glVertex3f(-SX,-SY,-SZ); glVertex3f(SX,-SY,-SZ); glVertex3f(SX,SY,-SZ); glEnd(); glDisable(GL_LIGHTING); // Get ready to draw the shadow and the ground // First disable lighting and save the projection state glPushMatrix(); // Multiply by shadow projection matrix glMultMatrixf((GLfloat *)shadowMat); // Now rotate the jet around in the new flattend space //glRotatef(xRot2, 1.0f, 0.0f, 0.0f); // glRotatef(yRot2, 0.0f, 1.0f, 0.0f); // Pass true to indicate drawing shadow DrawJet(1); // Restore the projection to normal glPopMatrix(); // Get ready to draw the shadow and the ground // First disable lighting and save the projection state glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glPushMatrix(); // Multiply by shadow projection matrix glMultMatrixf((GLfloat *)shadowMat2); // Now rotate the jet around in the new flattend space //glRotatef(xRot2, 1.0f, 0.0f, 0.0f); //glRotatef(yRot2, 0.0f, 1.0f, 0.0f); // Pass true to indicate drawing shadow DrawJet(1); // Restore the projection to normal glPopMatrix(); // Save the matrix state and do the rotations glPushMatrix(); // Draw jet at new orientation, put light in correct position // before rotating the jet glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); //glRotatef(xRot2, 1.0f, 0.0f, 0.0f); //glRotatef(yRot2, 0.0f, 1.0f, 0.0f); DrawJet(0); // Restore original matrix state glPopMatrix(); glDisable(GL_LIGHTING); // Draw the light source glPushMatrix(); glTranslatef(lightPos[0],lightPos[1], lightPos[2]); glColor3ub(255,255,0); glutSolidSphere(5.0f,10,10); glPopMatrix(); glEnable(GL_LIGHTING); // Restore lighting state variables glEnable(GL_DEPTH_TEST); glPopMatrix(); // Display the results Situation++; } glutSwapBuffers(); } |
Вывод:
Отражение, которое получается при рисовании прозрачной стену и прорисовки всей сцены за ней очень некачественное. Тень, получаемая с помощью рисования объекта на двумерной плоскости, на которой её нужно нарисовать выглядит достаточно правдоподобно.