В openGL, как вы можете получить элементы для рисования назад?

StackOverflow https://stackoverflow.com/questions/185536

  •  06-07-2019
  •  | 
  •  

Вопрос

По умолчанию кажется, что объекты нарисованы спереди назад. Я рисую двумерный объект пользовательского интерфейса и хотел бы создать его задом наперед. Например, я мог бы сначала создать белый квадрат, а затем создать чуть меньший черный квадрат поверх него, создав тем самым черную панель с белой рамкой. В этом посте было несколько обсуждений, и этот порядок описывался как " Алгоритм художника " но в конечном итоге приведенный ими пример просто отобразил объекты в обратном порядке, чтобы получить желаемый эффект. Я рассчитываю задом наперед (первые объекты возвращаются назад, последующие объекты рисуются сверху) рендеринга можно добиться с помощью некоторого преобразования (gOrtho?)?

Я также упомяну, что меня не интересует решение с использованием библиотеки-оболочки, такой как GLUT.

Я также обнаружил, что поведение по умолчанию на Mac с использованием Cocoa NSOpenGLView, похоже, отодвигает на задний план, где, как в окнах, я не могу получить это поведение. Код установки в окнах, которые я использую, таков:

glViewport (0, 0, wd, ht);
glMatrixMode(GL_PROJECTION);           
glLoadIdentity();                      
glOrtho (0.0f, wd, ht, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);             
glLoadIdentity();                       
Это было полезно?

Решение

Следующий вызов отключит проверку глубины, в результате чего объекты будут нарисованы в порядке их создания. Это фактически заставит объекты отрисовываться назад.

glDepthFunc(GL_NEVER);      // Ignore depth values (Z) to cause drawing bottom to top

Убедитесь, что вы не называете это так:

glEnable (GL_DEPTH_TEST);   // Enables Depth Testing

Другие советы

По вашему конкретному вопросу нет стандартизированного способа задания глубины упорядочения в OpenGL. Некоторые реализации могут по умолчанию выполнять упорядочение по глубине, поскольку оно обычно быстрее, но это не гарантировано (как вы обнаружили).

Но я не очень понимаю, как это поможет вам в вашем сценарии. Если вы рисуете черный квадрат перед белым квадратом, черный квадрат должен быть нарисован перед белым квадратом независимо от того, в каком порядке они нарисованы, если у вас включена буферизация глубины. Если они на самом деле копланарны, то ни один из них не стоит перед другим, и любой алгоритм сортировки по глубине будет непредсказуемым.

В руководстве, на которое вы разместили ссылку, говорилось только о том, что при использовании прозрачности важна глубинная сортировка. Но мне не кажется, что это то, что вы ищете.

Но если вам действительно нужно сделать это таким образом, то вы должны сделать это сами. Сначала отправьте белый квадрат в конвейер рендеринга, запустите рендеринг, а затем отправьте черный квадрат. Если вы сделаете это таким образом и отключите буферизацию глубины, квадраты могут быть копланарными, и вам все равно будет гарантировано, что черный квадрат нарисован над белым квадратом.

Порядок рисования сложный. Нет простого решения. Алгоритм художника (сортировка объектов по их расстоянию по отношению к виду вашей камеры) является наиболее простым, но, как вы обнаружили, он не решает все случаи.

Я бы предложил комбинацию альгроитма и слоев художника. Вы строите слои для определенных элементов в вашей программе. Итак, вы получили фоновый слой, слои объектов, слои спецэффектов и слой GUI.

Используйте алгоритм художника на элементах каждого слоя. В некоторых специальных слоях (например, в вашем слое GUI) сортировка выполняется не по алгоритму художника, а по порядку вызовов. Сначала вы называете этот белый квадрат, чтобы он был нарисован первым.

Нарисуйте элементы, за которыми вы хотите находиться, немного позади элементов, за которыми вы хотите находиться. То есть фактически измените значение z (при условии, что z перпендикулярен плоскости экрана). Вам не нужно сильно его менять, чтобы предметы рисовать перед собой. И если вы слегка измените значение z, вы не должны заметить значительного смещения от их желаемого положения. Вы можете даже пойти по-настоящему модно и рассчитать правильную позицию x, y на основе измененной позиции z, чтобы элемент появился там, где он должен быть.

Ваши вещи будут прорисованы в точном порядке, в котором вы вызываете функции glBegin / glEnd. Вы можете получить буферизацию глубины, используя z-буфер, и если ваши 2d-объекты имеют разные значения z, вы можете получить желаемый эффект сюда. Единственный способ увидеть поведение, которое вы описываете на Mac, - это если программа рисует вещи в обратном порядке вручную или использует z-буфер для этого. В противном случае OpenGL не имеет никакой функциональности, как вы описываете.

Как отметил AlanKley, способ сделать это - отключить буфер глубины. Алгоритм рисования - это действительно метод преобразования 2D-сканирования, используемый для визуализации полигонов в правильном порядке, когда у вас нет чего-то вроде z-буфера. Но вы не примените его к 3D полигонам. Обычно вы преобразуете и проецируете их (обрабатывает пересечения с другими полигонами), а затем сортируете результирующий список 2D проецируемых полигонов по их проецированной z-координате, а затем рисуете их в обратном z-порядке.

Я всегда думал об алгоритме художника как об альтернативной технике удаления скрытой поверхности, когда вы не можете (или не хотите) использовать z-буфер.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top