Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Программирование графики > Сбой буфера глубины? |
Автор: ksvsvk 26.07.18, 05:47 |
Из-за сбоя предыдущей темы, повторяю. Есть процедура, строящая помещение с зеркалами. Для краткости освещение и текстуры я из нее убрал, а из 6-ти поверхностей оставил одну, т.к. их построения однотипны. Скрытый текст <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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) в буфер глубины прописываются поверхности зеркал. Это позволяет осечь все, что находится за зеркалом, оставив объекты между зеркалом и наблюдателем. Поверхности зеркал при этом выглядят как черные прямоугольники: Скрытый текст
1.png (, : 467)
Далее вызывается рекурсивная процедура CreateMirror, которая определяет положение отражения, переворачивает соответствующую координату, отсекает ту часть "реального мира", которая расположена за зеркалом, и вызывает glCallList(1), в котором, как видно на предыдущем изображении, поверхность зеркала, попавшая в отражение, должна быть черной. Но вот в отражении эта "черная заливка" отсутствует: Скрытый текст
2.png (, : 466)
Почему? Как преобразование <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> glScalef(1, 1, -1); glTranslatef(0, 0, -2 * FirstNode.Z); повлияло на буфер глубины? PS не получилось вставить изображения, только ссылки на них |
Автор: OpenGL 26.07.18, 09:45 |
Не совсем понял проблему. Что ожидается на втором рисунке? Отсутствие белой задней (по отношению к камере) грани паралелепипеда (т.е. её окраска в чёрный цвет)? |
Автор: ksvsvk 27.07.18, 01:08 |
Отсутствующая грань колонны должна быть черной. |