Отключить / пропустить вершину в шейдере - PullRequest
3 голосов
/ 11 ноября 2011

Я рендерил огромное облако точек (1,5 млн. Точек) в виде GLPoints с WebGL и, естественно, сталкиваюсь с проблемами производительности.

Итак, моя первая идея - ограничить количество точек, нарисованных на экране. Особенно точки, удаленные от камеры, «бесполезны» и не должны отображаться.

Я сделал это, рассчитав расстояние между любой точкой и камерой. В моем вершинном шейдере я хотел бы отображать только точки, "достаточно близкие" к камере. Пока что я пытаюсь пропустить их, если расстояние «s» находится между камерой и плоскостью отсечения (отсюда и отрицательно).

if( s < 0.0){
  gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
  frontColor = vec4(0.0, 0.0, 0.0, 1.0);
  gl_PointSize = 0.0;
}else{
  gl_Position = ps_ProjectionMatrix * ecPos4;
}

Однако, вместо того, чтобы полностью пропустить вершину, она по-прежнему отображается (даже если я ее не вижу), как я могу судить по отображаемому FPS. Есть ли способ полностью отключить / пропустить / «удалить» вершину внутри вершинного шейдера?


Я вижу, как отбраковка усеченного конуса поможет ускорить процесс. Чтобы прояснить ситуацию, когда должен происходить отбор? Так как отбраковка должна пересчитываться после каждого движения камеры, должен ли я включить свой основной цикл? Однако делаю 1 млн. вычисления в цикле рендеринга не очень хорошая идея.

Правильно ли я понимаю, что, как только моя камера смотрит в совершенно ином направлении, чем мои точки, они должны автоматически обрезаться WebGl / оборудованием? Тем не менее, я чувствую, что отстранение от глаз не помогает. (FPS не пошел вверх) Может кто-нибудь, пожалуйста, немного elaborte!

Движок, который я использую, имеет матрицу проекции перспективы по умолчанию. Очевидно, что это влияет на координаты каждой вершины. Как матрица проекции связана с автоматическим отсечением?

Ответы [ 2 ]

2 голосов
/ 11 ноября 2011

Звучит так, как будто вам нужно настроить матрицу проецирования, чтобы усеченный вид вычеркнул те точки, которые находятся слишком далеко, чтобы внести существенный вклад в ваше изображение. Этот учебник от lighthouse3d содержит описание области просмотра и описывает методы реализации отбора на основе усеченного в программном обеспечении. Обратите внимание, что в вашем случае это не обязательно, поскольку OpenGL сделает это за вас, при условии, что вы правильно настроили матрицу проекций.

1 голос
/ 11 ноября 2011

Прежде всего, нет, нет.Вы не можете полностью отказаться от вершин.Каким будет треугольник из двух вершин (когда вы отбросите третью)?Вы можете сделать это на основе примитивов, используя геометрический шейдер, но это IMHO не поддерживается в WebGL.Даже если вы рисуете только точечные примитивы, вершинный шейдер по-прежнему не имеет представления о каких-либо примитивах и не может просто отбрасывать вершины.

Что вы можете сделать, это переместить вершину за пределы объема просмотра.Таким образом, он отсекается, и вам нужно платить только за вершинный шейдер, а не за растеризацию (которая в любом случае будет стоить дорого при использовании точек с размером 1), а также за фрагментный шейдер.

Это кажетсябудьте тем, что вы хотите сделать в данный момент, но на самом деле не очень хорошая идея установить координату w вершины в 0, что приводит к неопределенному поведению во время деления перспективы.Просто установите его вне объема канонического представления (куб [-1,1]):

if( s < 0.0 )
    gl_Position = vec4(2.0, 0.0, 0.0, 1.0);
else
    gl_Position = ps_ProjectionMatrix * ecPos4;

Вам также не нужно связываться с gl_PointSize.Достаточно установить его положение за пределами громкости просмотра.

РЕДАКТИРОВАТЬ: Но в вашем случае решение из ответа Джеймса намного проще.Просто измените дальнюю плоскость вашей проекционной матрицы, задача которой состоит в том, чтобы отсеивать слишком далеко объекты.

...