OpenGL — создайте границу над текстурированным полигоном

Я работаю с cocos2d-x 2.0.4. Я иллюстрирую то, что я пытаюсь сделать с помощью этих двух изображений.

convex_poly convex_poly_with_border

Что я хочу сделать, так это создать размытую границу или границу с градиентом на ней программно. У меня есть две идеи сделать это, но я не уверен, что это правильный способ сделать. Первым решением будет триангуляция многоугольника, содержащего только размытый цвет (в данном случае вогнутый многоугольник с отверстием) и отрисовка цвета на нем с градиентом, вершины снаружи многоугольника будут полностью альфа-каналами, а вершины внутри нулевыми. -альфа. Тогда интерполяция сделает работу градиента. Вторым решением было бы сделать это внутри самого шейдера. Все, что мне нужно, это вычислить расстояние от пикселя и ближайшего к нему края полигона. Затем при определенном пороге я воздействую на белый цвет пикселя с определенным значением альфы в зависимости от этого расстояния (самое короткое расстояние, самая большая альфа).

В любом случае, я очень новичок в openGL, и я боюсь, что второе решение приведет к большому времени обработки, так как мне нужно вычислить расстояние для каждого пикселя многоугольника. Что вы думаете об этом, ребята? Любые идеи, как правило, подтверждают мои догадки, или я полностью ошибаюсь в этом?

РЕДАКТИРОВАТЬ: решение, которое я, наконец, выбрал, состояло в том, чтобы использовать биссектрису каждого угла (легко вычислить с 3 последовательными вершинами) в многоугольнике и взять точку на этой биссектрисе, которая станет вершиной для внутреннего многоугольника. Затем я беру вершину внешнего или внутреннего многоугольника, чтобы построить массив вершин, который может соответствовать параметру GL_TRIANGLE_STRIP. Я поместил изображение ниже, чтобы понять лучше.

экспл


person olma    schedule 26.02.2013    source источник
comment
Просто общий комментарий, но вам нужно думать о треугольниках, а не о произвольных многоугольниках.   -  person JasonD    schedule 26.02.2013


Ответы (2)


Будет ли шейдер краевого освещения делать то, что вы хотите? Ссылка на пример

Пример кода для шейдера освещения обода GLSL:

const float rimStart = 0.5f;
const float rimEnd = 1.0f;
const float rimMultiplier = 0.0f;
vec3  rimColor = vec3(1.0f, 1.0f, 1.0f);

float NormalToCam = 1.0 - dot(normalize(outNormal), normalize(camPos - vertexWorldPos.xyz));
float rim = smoothstep(rimStart, rimEnd, NormalToCam) * rimMultiplier;

outColor.rgb += (rimColor * rim);
person MrLeap    schedule 26.02.2013
comment
Очень интересно, посмотрю ;) - person olma; 27.02.2013
comment
Я работаю над 2D-проектом, поэтому понятия глубины нет, и я думаю, что значение с плавающей запятой NormalToCam не имеет смысла в моем случае. Я храню его для своих будущих 3D-проектов ;) - person olma; 27.02.2013
comment
Ну, у вас еще есть понятие о глубине! Все просто имеет одну и ту же глубину. Интересно, не могли бы вы сделать нормали вдоль внешней точки полигональной точки ортогональной камере, а нормали внутренней точки параллельной камере. Это может заставить его работать на вас. В любом случае, я ПОДОЗРЕВАЮ, что эту технику можно как-то адаптировать. - person MrLeap; 27.02.2013
comment
В качестве альтернативы вы можете сделать это в несколько проходов рендеринга, в одном из которых вы немного масштабируете полигон, а затем делаете несколько проходов для размытия по Гауссу, а затем маскируете его против немодифицированного полигона. - person MrLeap; 27.02.2013

Чтобы это выглядело правильно с любой точки зрения в 3D-сцене, вам нужно будет выполнить некоторые силуэты. По сути, это включает в себя использование шейдера геометрии для определения того, у каких краев объекта есть смежная грань, обращенная к экрану, и смежная грань, не обращенная к экрану. Я полагаю, что этого можно достичь, проверив, является ли скалярное произведение между нормалью одной соседней грани и направлением вашей камеры ‹= 0, а точечный продукт другой нормали смежного лица и направлением вашей камеры > 0.

Как только вы узнаете все ребра, очерчивающие ваш многоугольник под определенным углом, вы можете тесселировать многоугольник, определяемый этой границей, в треугольные полосы (все еще в геометрическом шейдере). Затем вы передадите цвет каждой вершины вашему фрагментному шейдеру; где все вершины, лежащие на границе, передают цвет границы при полной альфе, а точки без границы передают цвет при нулевой альфе. Фрагментный шейдер будет интерполировать от цвета границы к центральному альфа-цвету на промежуточных фрагментах, давая вам нужный градиент. Ваш общий подход должен быть примерно таким:

  1. Нарисуйте объект с помощью программы шейдера без границ в качестве цвета фона.
  2. Включите альфа-смешивание.

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 
    
  3. Нарисуйте объект с помощью программы создания силуэта, определяя края, которые составляют границы, с цветом границы и рисуя точки, не являющиеся границами, как нулевую альфу.

  4. glDisable(GL_BLEND);
    
person Sir Digby Chicken Caesar    schedule 26.02.2013
comment
На самом деле это 2D-проект, но ваш метод подтверждает мой, и я думаю, что это должно сработать. Спасибо;) - person olma; 27.02.2013
comment
Без проблем! Я так привык думать в трехмерном пространстве, что совершенно забыл, что люди использовали OpenGL для двухмерного рисования. Удачи! - person Sir Digby Chicken Caesar; 27.02.2013