// создаётся текстура, один раз, при инициализации OPENGL. ShadowTexture = funShadowTexture(); // ЦИКЛ void Draw (void) { renderToShadowMap(); // Здесь рендерится карта тени renderWithShadow(); // Здесь рендерится сцена с тенью } /////////////////////////////////////////////////////////////////////////////////////////// /// /// ТЕКСТУРА ДЛЯ ТЕНИ /// /////////////////////////////////////////////////////////////////////////////////////////// GLuint funShadowTexture() { GLuint texture;// Место для одной текстуры // Создание текстуры glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // Фильтрация текстуры, линейная glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // фильтрация как для обычной текстуры (смазанные тексели) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // фильтрация как для обычной текстуры (смазанные тексели) // Тип распространения текстуры, не копирующаяся glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); // Цвет за пределами текстуры - НЕработает :) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, ( 1.0f, 1.0f, 1.0f, 1.0f) ); // способ хранения текстуры, для хранения используются все 4 канала - RGBA glTexParameteri(GL_TEXTURE_2D,GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); // // положение текстуры, из глаз, в данном случае из положения ист. света glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); glTexGeni ( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); glTexGeni ( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); // сравнение глубины пикселя, ОСНОВНАЯ ФИШКА ТАКОЙ ТЕКСТУРЫ. ЕСЛИ ГЛУБИНА ПИКСЕЛЯ СОВПАДАЕТ С ГЛУБИНОЙ ТЕКСЕЛЯ ТЕКСТУРЫ // ТО ЦВЕТ ПИКСЕЛЯ БЕЛЫЙ, ЕСЛИ НЕ СОВПАДАЕТ, ТО ЧЁРНЫЙ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); return (texture); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Запись буфера глубины с позиции источника света /// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void renderToShadowMap() { // - 0 shadowMapSize = ResolutionScreenY; // Качество тени, разрешение экрана по вертикали, НЕ БОЛЬШЕ. //карта должна быть квадратной. glMatrixMode(GL_PROJECTION); // Выберем матрицу проекции glLoadIdentity(); //Сбросим матрицу glViewport (0, 0, (GLsizei)(shadowMapSize), (GLsizei)(shadowMapSize)); // Задаётся квадратный glViewport :) gluPerspective(45.0f, (GLfloat)(shadowMapSize)/(GLfloat)(shadowMapSize), 1.0f, 200.0f); // - думаю понятно glGetFloatv(GL_PROJECTION_MATRIX, LightProjection); // сохраняем матрицу для дальнейшего использования glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0.0f, 0.0f, 0.0f); gluLookAt (lightX, lightZ, lightY, // Положение камеры - откуда светит свет 0.0f, 0.0f, 0.0f, // координаты направления камеры 0.0f, 0.0f, 1.0f); glGetFloatv (GL_MODELVIEW_MATRIX, LightModelviev); // сохраняем матрицу для дальнейшего использования glClear (GL_DEPTH_BUFFER_BIT); // отчищяем буфер глубины glEnable(GL_POLYGON_OFFSET_FILL); // не помню что она включает НО, glPolygonOffset(3.0f, 0.0f); // с помощью этоё функции можно смещять тень, это понадобится для того чтобы избавиться от артефактов //--------------------- ..... отключает текстурирование, освещение и т.д., должно остаться только расчёт глубины //--------------------- RenderScen(LightProjection, LightModelviev); // РИСУЕТСЯ СЦЕНА, с позиции света. glBindTexture(GL_TEXTURE_2D, ShadowTexture); // GL_DEPTH_COMPONENT - сохраняет буфер глубины в текстуру glCopyTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, (GLsizei)shadowMapSize, (GLsizei)shadowMapSize, 0 ); glDisable(GL_POLYGON_OFFSET_FILL); // отключаем ту фигню :) //------------------------------------------ glMatrixMode (GL_TEXTURE); glLoadIdentity (); // требуется сдвинуть матрицу текстуры, для того чтобы она проецировалась по центру (из 0:1 в -0.5 : 0.5) glTranslatef (0.5f, 0.5f, 0.5f); glScalef (0.5f, 0.5f, 0.5f); // матрици текстуры перемножается с ЭТИМИ матрицами glMultMatrixf(LightProjection); glMultMatrixf(LightModelviev); // - ПРИ РЕНДЕРЕ СЦЕНЫ С ТЕНЬЮ, БУДЕТ ИСПОЛЬЗОВАТЬСЯ ДАННАЯ ТЕКСТУРНАЯ МАТРИЦА (а не та которая объчно испотльзуется для текстурирования), //КОТОРАЯ ОРИЕНТИРОВАННА не НА КАМЕРУ НАБЛЮДАТЕЛЯ, А НА ИСТОЧНИК СВЕТА } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Отображение сцены с позиции НАБЛЮДАТЕЛЯ, с тенью. /// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// void renderWithShadow() { // - 0 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очищаем как объчно glMatrixMode(GL_PROJECTION); // Выберем матрицу проекции, как обычно glLoadIdentity(); glViewport (0, 0, (GLsizei)(ResolutionScreenX), (GLsizei)(ResolutionScreenY)); // как обычно // ДАЛЬНОСТЬ ПРОРИСОВКИ ДОЛЖНА БЫТЬ ТАКОЙ ЖЕ КАК У ТЕНИ, НО МОЖЕТ БЫТЬ СМЕЩЕНА (например: тень=51-250, камера=1-200 ) gluPerspective(45.0f, (GLfloat)(ResolutionScreenX)/(GLfloat)(ResolutionScreenY), 1.0f, 200.0f); glGetFloatv(GL_PROJECTION_MATRIX, CameraProjection); glMatrixMode (GL_MODELVIEW); glLoadIdentity (); My_Camera (); // - положение наблюдателя glGetFloatv (GL_MODELVIEW_MATRIX, CameraModelviev); // здесь я особо не разбирался, это ВРОДЕ задаются параметры распространения текстуры // С УЧЁТОМ МАТРИЦИ ТЕКСТУРЫ ИЗ ПОЛОЖЕНИЯ ИСТ. СВЕТА GLfloat sPlane[4] = {1.0f, 0.0f, 0.0f, 0.0f}; GLfloat tPlane[4] = {0.0f, 1.0f, 0.0f, 0.0f}; GLfloat rPlane[4] = {0.0f, 0.0f, 1.0f, 0.0f}; GLfloat qPlane[4] = {0.0f, 0.0f, 0.0f, 1.0f}; glEnable ( GL_TEXTURE_GEN_S ); glEnable ( GL_TEXTURE_GEN_T ); glEnable ( GL_TEXTURE_GEN_R ); glEnable ( GL_TEXTURE_GEN_Q ); glTexGenfv ( GL_S, GL_EYE_PLANE, sPlane ); glTexGenfv ( GL_T, GL_EYE_PLANE, tPlane ); glTexGenfv ( GL_R, GL_EYE_PLANE, rPlane ); glTexGenfv ( GL_Q, GL_EYE_PLANE, qPlane ); // РУСУЕТСЯ СЦЕНА, С МУДРЁНОЙ ТЕКСТУРОЙ, ЦВЕТ КОТОРОЙ ЗАВИСИТ ОД ГЛУБИНЫ ПИКСЕЛЯ RenderScen(CameraProjection, CameraModelviev); // РИСУЕТСЯ СЦЕНА glDisable ( GL_TEXTURE_GEN_S ); glDisable ( GL_TEXTURE_GEN_T ); glDisable ( GL_TEXTURE_GEN_R ); glDisable ( GL_TEXTURE_GEN_Q ); }