На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
! Правила раздела "Программирование графики"
1) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с чтением, сохранением, обработкой, созданием, отрисовкой графической информации (в том числе - 3D [OpenGL, Direct3D] и анимации [в т.ч. VFW, DirectShow, OpenDML]).
Флэш обсуждают здесь!.

2) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе.

3) Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно.



Ваше мнение о модераторах: user posted imageBarazuk, user posted imageOpenGL, user posted imageMikle
Модераторы: OpenGL, Mikle
  
> Сбой буфера глубины?, Построение отражения поверхности зеркала.
    Из-за сбоя предыдущей темы, повторяю.

    Есть процедура, строящая помещение с зеркалами. Для краткости освещение и текстуры я из нее убрал, а из 6-ти поверхностей оставил одну, т.к. их построения однотипны.
    Скрытый текст
    ExpandedWrap disabled
      procedure TGLForm.GenList;
       
        procedure CreateMirror(Level: Byte);
        var
          i, j: GLUint;
          Pl:   array [0..3] of GLDouble;
        begin
          {$REGION 'code'}
          for i := 0 to High(Areas) do with Areas[i] do
          for j := 0 to 5 do
          if Level <= Surfaces[j].Mirror then
          begin
            glPushMatrix;
            case j of
              {$REGION 'Координаты отражений'}
              0:  begin
                    glScalef(1, 1, -1);
                    glTranslatef(0, 0, -2 * FirstNode.Z);
                  end;
              {$ENDREGION}
            end;
            CreateMirror(Level + 1);
            glClear(GL_STENCIL_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
            glStencilFunc(GL_NEVER, 1, 255);
            glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
            case j of
              0:  {$REGION 'Зеркальный пол'}
                  begin
                    glBegin(GL_QUADS);
                      glVertex3f(FirstNode.X,  FirstNode.Y,  FirstNode.Z);
                      glVertex3f(FirstNode.X,  SecondNode.Y, FirstNode.Z);
                      glVertex3f(SecondNode.X, SecondNode.Y, FirstNode.Z);
                      glVertex3f(SecondNode.X, FirstNode.Y,  FirstNode.Z);
                    glEnd;
                    Pl[0] := 0; Pl[1] := 0; Pl[2] := 1;
                    Pl[3] := FirstNode.Z;
                  end;
                  {$ENDREGION}
            end;
            glClipPlane(GL_CLIP_PLANE0, @Pl);
            glEnable(GL_CLIP_PLANE0);
            glCallList(1);
            glDisable(GL_CLIP_PLANE0);
            glPopMatrix;
          end;
          {$ENDREGION}
        end;
       
      var
        {$REGION 'var'}
        i, j, k:    GLUint;
        C:          TColor;
        Colors:     array [0..3] of GLFloat;
        PosLamp:    array [0..3] of GLFloat;
        DirLamp:    array [0..2] of GLFloat;
        Coord:      TDoubleRect;
        Surf: array of array [0..1] of Cardinal;
        {$ENDREGION}
      begin
        {$REGION 'code'}
        glDeleteLists(1, 3);
        MaxCount.X := 0; MaxCount.Y := 0; MaxCount.Z := 0;
        MinCount.X := 0; MinCount.Y := 0; MinCount.Z := 0;
        glNewList(1, GL_COMPILE);
          {$REGION 'Основной объем'}
          Colors[3] := 0;
          glLineWidth(1);
          {$REGION 'Глубина зеркал'}
          glDrawBuffer(GL_NONE);
          glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
          for k := Low(Areas) to High(Areas) do with Areas[k] do
          begin
            if Surfaces[0].Mirror > 0 then
            begin
              if MinCount.Z < Surfaces[0].Mirror
              then MinCount.Z := Surfaces[0].Mirror;
              glBegin(GL_QUADS);
                glVertex3f(FirstNode.X,  FirstNode.Y,  FirstNode.Z);
                glVertex3f(SecondNode.X, FirstNode.Y,  FirstNode.Z);
                glVertex3f(SecondNode.X, SecondNode.Y, FirstNode.Z);
                glVertex3f(FirstNode.X,  SecondNode.Y, FirstNode.Z);
              glEnd;
            end;
          end;
          {$ENDREGION}
          for k := Low(Areas) to High(Areas) do with Areas[k] do
          begin
            {$REGION 'Пол'}
              glDrawBuffer(GL_NONE);
              {$REGION 'Генерация карты перекрытия'}
                glStencilFunc(GL_LESS, 1, 255);
                glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
                glDisable(GL_DEPTH_TEST);
                {$REGION 'Анулирование зоны перекрытия'}
                glBegin(GL_QUADS);
                  glVertex3f(FirstNode.X, FirstNode.Y, FirstNode.Z);
                  glVertex3f(SecondNode.X, FirstNode.Y, FirstNode.Z);
                  glVertex3f(SecondNode.X, SecondNode.Y, FirstNode.Z);
                  glVertex3f(FirstNode.X, SecondNode.Y, FirstNode.Z);
                glEnd;
                {$ENDREGION}
                glStencilFunc(GL_EQUAL, 1, 255);
                glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
                for i := Low(Areas) to High(Areas) do
                  if (i <> k)and
                   (((Areas[i].FirstNode.Z < FirstNode.Z)and(Areas[i].SecondNode.Z > FirstNode.Z)or
                     (Areas[i].SecondNode.Z = FirstNode.Z)or(Areas[i].FirstNode.Z = FirstNode.Z)and(i > k))and
                     (Areas[i].SecondNode.X >= FirstNode.X)and(Areas[i].FirstNode.X <= SecondNode.X)and
                     (Areas[i].SecondNode.Y >= FirstNode.Y)and(Areas[i].FirstNode.Y <= SecondNode.Y))then
                  begin
                    glBegin(GL_QUADS);
                      glVertex3f(Areas[i].FirstNode.X, Areas[i].FirstNode.Y, Areas[k].FirstNode.Z);
                      glVertex3f(Areas[i].SecondNode.X, Areas[i].FirstNode.Y, Areas[k].FirstNode.Z);
                      glVertex3f(Areas[i].SecondNode.X, Areas[i].SecondNode.Y, Areas[k].FirstNode.Z);
                      glVertex3f(Areas[i].FirstNode.X, Areas[i].SecondNode.Y, Areas[k].FirstNode.Z);
                    glEnd;
                  end;
                glEnable(GL_DEPTH_TEST);
                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
              {$ENDREGION}
              glDrawBuffer(GL_BACK);
              {$REGION 'Выбор цвета'}
                {$REGION 'Цвет'}
                for j := 0 to 3 do
                begin
                  C := Surfaces[0].Colors[j];
                  Colors[0] := (C and 255)/ 255;
                  C := C shr 8;
                  Colors[1] := (C and 255)/ 255;
                  C := C shr 8;
                  Colors[2] := (C and 255)/ 255;
                  case j of
                    0: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, @Colors);
                    1: glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, @Colors);
                    2: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, @Colors);
                    3: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, @Colors);
                  end;
                end;
                {$ENDREGION}
              {$ENDREGION}
              if Surfaces[0].Mirror = 0 then
              begin
                glBegin(GL_QUADS);
                  {$REGION 'Построение полигонов'}
                  try
                    Coord.Left    := Surfaces[0].Left   / Images[Surfaces[0].Tex - 1].Width;
                    Coord.Rigth   := Surfaces[0].Right  / Images[Surfaces[0].Tex - 1].Width;
                    Coord.Bottom  := Surfaces[0].Top    / Images[Surfaces[0].Tex - 1].Height;
                    Coord.Top     := Surfaces[0].Bottom / Images[Surfaces[0].Tex - 1].Height;
                  except
                  end;
                  glNormal3f(0.0, 0.0, 1.0);
                  for i := 0 to Count.X - 1 do
                  for j := 0 to Count.Y - 1 do
                  begin
                    glVertex3f(FirstNode.X + i * Abs(FirstNode.X - SecondNode.X)/Count.X,
                               FirstNode.Y + j * Abs(FirstNode.Y - SecondNode.Y)/Count.Y,
                               FirstNode.Z);
                    glVertex3f(FirstNode.X +(i + 1)* Abs(FirstNode.X - SecondNode.X)/Count.X,
                               FirstNode.Y + j * Abs(FirstNode.Y - SecondNode.Y)/Count.Y,
                               FirstNode.Z);
                    glVertex3f(FirstNode.X +(i + 1)* Abs(FirstNode.X - SecondNode.X)/Count.X,
                               FirstNode.Y +(j + 1)* Abs(FirstNode.Y - SecondNode.Y)/Count.Y,
                               FirstNode.Z);
                    glVertex3f(FirstNode.X + i * Abs(FirstNode.X - SecondNode.X)/Count.X,
                               FirstNode.Y +(j + 1)* Abs(FirstNode.Y - SecondNode.Y)/Count.Y,
                               FirstNode.Z);
                  end;
                  {$ENDREGION}
                glEnd;
              end;
            {$ENDREGION}
          {$ENDREGION}
        glEndList;
        glNewList(2, GL_COMPILE);
          {$REGION 'Зеркальные поверхности'}
          glClearStencil(0);
          CreateMirror(1);
          glClearStencil(1);
          glClear(GL_STENCIL_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
          glCallList(1);
          {$ENDREGION}
        glEndList;
      end;



    В ней реализован следующий подход:

    1. Перед построением "физического мира" в списке glNewList(1) в буфер глубины прописываются поверхности зеркал. Это позволяет осечь все, что находится за зеркалом, оставив объекты между зеркалом и наблюдателем. Поверхности зеркал при этом выглядят как черные прямоугольники:

    Скрытый текст
    Прикреплённая картинка
    Прикреплённая картинка


    Далее вызывается рекурсивная процедура CreateMirror, которая определяет положение отражения, переворачивает соответствующую координату, отсекает ту часть "реального мира", которая расположена за зеркалом, и вызывает glCallList(1), в котором, как видно на предыдущем изображении, поверхность зеркала, попавшая в отражение, должна быть черной. Но вот в отражении эта "черная заливка" отсутствует:

    Скрытый текст
    Прикреплённая картинка
    Прикреплённая картинка


    Почему? Как преобразование

    ExpandedWrap disabled
        glScalef(1, 1, -1);
        glTranslatef(0, 0, -2 * FirstNode.Z);


    повлияло на буфер глубины?

    PS не получилось вставить изображения, только ссылки на них :(
    Сообщение отредактировано: OpenGL -
      Не совсем понял проблему. Что ожидается на втором рисунке? Отсутствие белой задней (по отношению к камере) грани паралелепипеда (т.е. её окраска в чёрный цвет)?
      Подпись была включена в связи с окончанием срока наказания
        Отсутствующая грань колонны должна быть черной.
        1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script Execution time: 0,1365 ]   [ 16 queries used ]   [ Generated: 22.10.19, 11:27 GMT ]