Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: __Heaven__ от Июль 31, 2014, 16:55



Название: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 16:55
Здравствуйте!
Я заинтересовался вопросом, как поверх нарисованных мною полигонов нарисовать сетку.
При обычном наложении сетки на полигоны возникала, так называемая z-fighting.
В интернете я нашёл функцию glPolygonOffset(-1.0, -1.0). На что указывают её аргументы, так и не смог понять.
В прикрепленном файле имеется две детали. Одна вставлена во вторую. Поверхности, которые не видны, я вычислять не хотел бы (по крайней мере на процессоре), так как мне очень критична скорость. На рисунке видно, как сквозь синюю деталь, обшитую белыми линиями, просачиваются чёрные, принадлежащие красной детали (при поворотах видны иногда и соседние белые, которые за поверхностью).
Данные о вершинах поступают таким образом, что невозможно определить переднюю сторону полигона.
Каким образом можно ликвидировать это неверное наложение?


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Июль 31, 2014, 17:09
Поверхности, которые не видны, я вычислять не хотел бы (по крайней мере на процессоре), так как ..
Ну а я просто "не знаю как" (без разницы хотел или нет  :)). Делал подобное 2 дня назад - просто второй проход напр glDrawArrays(GL_LINES..), можно толщину линии увеличить.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 17:46
У меня проще. Детали идеально соприкасаются по элементам. Вычислить эти элементы и вуаля.
Можно, пожалуйста подробнее, с кодом. Я только успел изучить 5 глав суперкниги и на разбор документации времени нет.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 18:00
Сразу не понял сообщения…
Так я второй проход и делаю. Получается то, что на рисунке
Обратите внимание на силуэт красного тела. Его не должно быть. Две вертикальные черные линии на синем теле лишние
Увеличение толщины сделает их только заметнее


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Июль 31, 2014, 18:10
У меня юзверь выбирает как рисовать (с заливкой, wireframe и др), поэтому данные wireframe хранятся как ребра/линии и просто рисуются вторым проходом. Если Вам нет нужды создавать такие данные (есть только полигоны), то попробуйте вторым проходом напр
Код
C++ (Qt)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

Сразу не понял сообщения…
Так я второй проход и делаю. Получается то, что на рисунке
Обратите внимание на силуэт красного тела. Его не должно быть. Две вертикальные черные линии на синем теле лишние
Увеличение толщины сделает их только заметнее
Не связывайтесь с glPolygonOffset


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 18:25
У меня данные хранятся в виде массива координат вершин (xyzxyzxyz)
Если я делаю без полигон офсет, то получаю z конфликт на пересечении линии и поверхности. То есть сетка получается бегающим пунктиром. Меня не устраивает, что линии полностью не прокрашиваются. Позже готов предоставить скрин.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 18:26
Юзверь, это сленг юзер?


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Июль 31, 2014, 18:53
У меня данные хранятся в виде массива координат вершин (xyzxyzxyz)
Если я делаю без полигон офсет, то получаю z конфликт на пересечении линии и поверхности. То есть сетка получается бегающим пунктиром. Меня не устраивает, что линии полностью не прокрашиваются. Позже готов предоставить скрин.
Как выводили "бегающую" сетку - это неясно из Вашего поста, поэтому трудно что-то советовать. Пробуйте glPolygonMode, не устраивает - выводите линиями, их всегда можно получить из полигонов. Проверить оба варианта максимум час, действуйте более конкретно/целеустремленно.   


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Июль 31, 2014, 19:43
Во вложении 3 картинки. Первая это с применением оффсет. Вторая без применения оффсет. Третья - то же, что и вторая, только повернута немного и наклонена.
Без применения оффсета сетка мелькает при повороте, превращаясь в пунктиры, пропадая частично. То есть, идёт борьба между первым проходом полигонов и вторым, с wire.

Мой код, к сожалению остался на работе - выкладываю старый, но, эффект прослеживается такой же:

Код:
void Positioner::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float* otlData = otlVertexes.data();
    float* formData = formVertexes.data();

    glPushMatrix();

    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);
    glRotatef(zRot, 0.0f, 0.0f, 1.0f);

    glTranslatef(-geomCenter[0], -geomCenter[1], -geomCenter[2]);

    glBegin(GL_TRIANGLES);
        if (showCastBtn->isChecked())
        {
            glColor3f(1.0f, 0.0f, 0.0f);
            for (int i = 0; i < otlVertexes.size(); i += 3)
                glVertex3fv(otlData + i);
        }
        if (showMouldBtn->isChecked())
        {
            glColor3f(0.0f, 0.0f, 1.0);
            for (int i = 0; i < formVertexes.size(); i += 3)
                glVertex3fv(formData + i);
        }

    glEnd();

    glColor3f(0.0f, 0.0f, 0.0f);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//    glEnable(GL_POLYGON_OFFSET_LINE);
    glPolygonOffset(-0.5f, -1.0f);
    glBegin(GL_TRIANGLES);
        if (showCastBtn->isChecked())
        {
            for (int i = 0; i < otlVertexes.size(); i += 3)
                glVertex3fv(otlData + i);
        }
        if (showMouldBtn->isChecked())
        {
            glColor3f(1.0f, 1.0f, 1.0f);
            for (int i = 0; i < formVertexes.size(); i += 3)
                glVertex3fv(formData + i);
        }
    glEnd();
    glDisable(GL_POLYGON_OFFSET_LINE);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//    glPolygonOffset(0.0f, 0.0f);


    glPopMatrix();
}

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


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 01, 2014, 10:45
Вот поправленный код:
Код:
void Positioner::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float* otlData = otlVertexes.data();
    float* formData = formVertexes.data();

    glPushMatrix();

    glRotatef(xRot, 1.0f, 0.0f, 0.0f);
    glRotatef(yRot, 0.0f, 1.0f, 0.0f);
    glRotatef(zRot, 0.0f, 0.0f, 1.0f);

    glTranslatef(-geomCenter[0], -geomCenter[1], -geomCenter[2]);

    if (showCastBtn->isChecked())
    {
        glColor3f(1.0f, 0.0f, 0.0f);
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, otlData);
        glDrawArrays(GL_TRIANGLES, 0, otlVertexes.size() / 3);

        glEnable(GL_POLYGON_OFFSET_LINE);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glColor3f(0.0f, 0.0f, 0.0f);
        glDrawArrays(GL_TRIANGLES, 0, otlVertexes.size() / 3);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

        glDisable(GL_POLYGON_OFFSET_LINE);
        glDisableClientState(GL_VERTEX_ARRAY);
    }
    if (showMouldBtn->isChecked())
    {
        glColor3f(0.0f, 0.0f, 1.0f);
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, formData);
        glDrawArrays(GL_TRIANGLES, 0, formVertexes.size() / 3);

        glEnable(GL_POLYGON_OFFSET_LINE);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glColor3f(1.0f, 1.0f, 1.0f);
        glDrawArrays(GL_TRIANGLES, 0, formVertexes.size() / 3);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisable(GL_POLYGON_OFFSET_LINE);
    }

    glPopMatrix();
}


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 01, 2014, 11:18
__Heaven__, не то чтобы я Вас "понукаю", но вещи должны делаться в нормальном, рабочем темпе. Проверили glPolygonMode, не выходит. Чего ждем? Проверяем вариант с отрисовкой линий (который работает у меня). Хотя бы "на коленке", glBegin(GL_LINES) и.т.д


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 01, 2014, 11:49
Igors, не сразу понял ваше предложение.
Не успех... Результат на коленке с использованием линий дает тот же результат z блокировки.
Код:
//        glEnable(GL_POLYGON_OFFSET_LINE);
//        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//        glColor3f(1.0f, 1.0f, 1.0f);
//        glDrawArrays(GL_TRIANGLES, 0, formVertexes.size() / 3);
//        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//        glDisableClientState(GL_VERTEX_ARRAY);
//        glDisable(GL_POLYGON_OFFSET_LINE);
        glColor3f(1.0f, 1.0f, 1.0f);
        float* pEnd = formData + formVertexes.size();
        glBegin(GL_LINES);
        for (;formData < pEnd; formData += 3*3)
        {
            glVertex3fv(formData);
            glVertex3fv(formData+3);

            glVertex3fv(formData);
            glVertex3fv(formData+6);

            glVertex3fv(formData+3);
            glVertex3fv(formData+6);

        }
        glEnd();


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 01, 2014, 12:03
Увеличение размера линии тоже не помогло.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 01, 2014, 14:03
Igors, можно посмотреть ваш код?


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 02, 2014, 11:31
Igors, можно посмотреть ваш код?
Нет возможности выдрать его из большого проекта. Пока не смог добиться у себя ощутимого мерцания. Поэкспериментирую еще - отпишусь


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 02, 2014, 14:05
Спасибо за участие


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 02, 2014, 14:43
Ну в общем этот есть и у меня, просто рендерю с анти-алиасом и цвет сетки 0.5 (благородный мышиный), поэтому дефект мало заметен - при кручении сцены линии сетки становятся толще/тоньше но не исчезают. При этом рисование линиями дает чуть лучший результат. Погуглил, да, штатное средство glPolygonOffset, но все мои попытки его задействовать ни к чему не привели. Вот "вдавить" сетку - пожалуйста, но это не нужно. А наоборот - все равно линии "играют". Неск лет назад пробовал с тем же рез-том - артефакты появляются, а качества сетки так и нет. Да, и полного единодушия в гугле нет, предлагаются какие-то альтернативные решения, типа "проблема актуальна".

Сейчас у меня еще геморрой - нужно выбирать вертексы с OpenGL, ситуация похожая - да, вроде есть средства, но какого-то четкого решения не видно. В общем OpenGL - это "Блеск и нищета куртизанок"  :)


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 04, 2014, 08:28
На gamedev мне ответили
Цитировать
Я решил эту проблему рисованием сетки в геометрическом шейдере
Что это и как с этим работать? Меня пугает слово "шейдер". Это что-то сложное и долгое в изучении?

Попробовал с антиальясингом (16 сэмплов) - результат не удовлетворил. При повороте плоскости перпендикулярно обзору получается, что все линии с поверхности пропадают. При стандартной толщине линии.

Как-то, ведь, это делается... В hyper mesh чувствуется, сделано без сглаживания.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 04, 2014, 10:14
На gamedev мне ответили
Цитировать
Я решил эту проблему рисованием сетки в геометрическом шейдере
Что это и как с этим работать? Меня пугает слово "шейдер". Это что-то сложное и долгое в изучении?
Ну в общем да, не мед, программирование на GLSL очень специфично

Как-то, ведь, это делается... В hyper mesh чувствуется, сделано без сглаживания.
Из этого не следует что нужно только "нажать бубочку" (т.е. вызвать нужную ф-цию) и "вуаля". Конечно это было бы здОрово, но нет гарантии что это найдется. Если бы меня "припекло" я бы "приподнял" линии пересчитав для них вертексы (сдвинул бы их по нормалям) - ну это достаточно много писать


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 04, 2014, 11:09
Печаль...
Ладно, как найду решение - отпишусь


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 07, 2014, 18:36
Работает, "магические числа" (-2, -2) для второго прохода (рисование сетки)
Первоисточник http://www.felixgers.de/teaching/jogl/polygonOffset.html (http://www.felixgers.de/teaching/jogl/polygonOffset.html)


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 08, 2014, 11:54
Магия не удалась. Сетка пробивается с задних слоёв.

Обрезал проект. (см. аттач)
для прорисовки необходимо открыть файлик геометрии из папки testFiles.
Так станет яснее моя проблема. Очень заметна проблема в исходном положении поворота. При вращении тоже линии просачиваются.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 27, 2014, 21:31
Я не знаю, почему я не догадался сделать это сразу, но сегодня я это сделал.
Вот что я сделал: создал 4 спинбокса для регулирования factor и unit полигон оффсетов заливки и сетки в режиме рантайм.
Долго игрался со спинбоксами - вращал модель. В общем, изголялся над своим детищем и собой.

Получается, что проблему решил, но осталось несколько вопросов.

Изначально ход мыслей был такой:
Имеется функция glDepthFunc, которая задаёт функцию сравнения глубины. По умолчанию её значение равно GL_LESS. Я подумал, что если я поставлю GL_LEQUAL, то при конфликте сетка-заливка будет прорисовываться только сетка. В итоге нет, даже антиальясинг и увеличение толщины линии не дали желаемого эффекта. Почему?

Далее я сделал предположение, что factor и units должны динамичеки изменяться от угла поворота (что судя по всему не так). Во время игр с цифрами пришёл к выводу, что сетку можно и не трогать, достаточно притопить заливку на фактор 0,7 и количество юнитов 0,3.

Игорь, огромная просьба к вам проверить эти значения в своем проекте без антиальясинга.
P.S.: во вложении отрисована КЭ модель без использования освещения  ;)


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Август 28, 2014, 06:45
Изначально ход мыслей был такой:
Имеется функция glDepthFunc, которая задаёт функцию сравнения глубины. По умолчанию её значение равно GL_LESS. Я подумал, что если я поставлю GL_LEQUAL, то при конфликте сетка-заливка будет прорисовываться только сетка. В итоге нет, даже антиальясинг и увеличение толщины линии не дали желаемого эффекта. Почему?
Для одной и той же точки: на первом проходе (с заливкой) depth вычисляется одним способов, на втором (линии) другим. Полученные значения очень близки но все же отличаются на какие-то микроны (в обе стороны) - ну просто так работают флоты. Поэтому GL_LEQUAL улучшает ситуацию но полностью проблему не решает.

Насколько я понял, сейчас принято это решать в шейдере используя gl_FragDepth

Игорь, огромная просьба к вам проверить эти значения в своем проекте без антиальясинга.
Слишком много завязано на AA, я не могу его просто так отключить. А с ним (0.7, 0.3) все то же - да, нормально, устраивает, но все-таки когда модель крутим интерактивно - какое-то подмигивание сетки есть


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 28, 2014, 07:22
Спасибо за быстрый ответ. Надеюсь, что сетка мигает из-за эффекта антиальясинга.
Все равно не понимаю, как так происходят вычисления, что 2+2=4, а потом 2+2=4+1E-100500
Мне казалось, что в первом приближении мы получаем глубину вершин, которая высчитывается одинаковыми методами и равна одному и тому же значению. Далее интерполируется область между вершинами. Не представляю, как её можно считать иначе.... Ну, наверное, это моя неосведомлённость в математике.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Old от Август 28, 2014, 07:37
Все равно не понимаю, как так происходят вычисления, что 2+2=4, а потом 2+2=4+1E-100500
Грубо говоря - Да.
С плавающей арифметикой это нормально, не все реальные числа можно представить числами с плавающей точкой.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 28, 2014, 07:46
Я это понимаю. Но дело в том, что у меня входные параметры в обоих случаях одинаковые и являются массивом float


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Old от Август 28, 2014, 07:54
Я это понимаю. Но дело в том, что у меня входные параметры в обоих случаях одинаковые и являются массивом float
У вас да, но opengl тоже считает используя числа с плавающей запятой.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 28, 2014, 08:11
Я понял, что просто накапливается разная погрешность при каждой отрисовки.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Old от Август 28, 2014, 08:36
Я понял, что просто накапливается разная погрешность при каждой отрисовки.
Я бы не назвал это накапливанием погрешности, результаты нигде не накапливаются - все пересчитывается с нуля.
Скорее в результате пересчета получилось число, которое в двоичном виде (в числе с плавающей точкой) представить нельзя, и поэтому оно немного "скорректировалось", что бы туда вписаться.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: __Heaven__ от Август 28, 2014, 08:42
А разве сама карта вычисляет не во float?


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Old от Август 28, 2014, 08:48
А разве сама карта вычисляет не во float?
Я надеюсь что в double, но это такие же числа с плавающей точкой, только точность у них выше.


Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Igors от Сентябрь 02, 2014, 08:35
А разве сама карта вычисляет не во float?
Я надеюсь что в double, но это такие же числа с плавающей точкой, только точность у них выше.
Вряд ли. Напр при подаче double в VBO наблюдал обратный эффект - замедление вместо ускорения.

А что алгоритмы рисования линий и закраски полигонов различны - достаточно очевидно. При рисовании линий интерполируются 2 координаты, при закраске 3, и третья совсем не обязана быть чистым нулем.



Название: Re: Прорисовка сетки поверх полигонов
Отправлено: Old от Сентябрь 02, 2014, 08:44
Вряд ли. Напр при подаче double в VBO наблюдал обратный эффект - замедление вместо ускорения.
Точно, посмотрел в презенташки NVIDIA, у них 32 битный float.