2013-02-26 2 views
1

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

convex_poly http://img542.imageshack.us/img542/2554/convexpoly.png convex_poly_with_border http://img40.imageshack.us/img40/8007/convexpolywithborder.png

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

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

EDIT: Решение, которое я, наконец, выбрал, состоял в том, чтобы использовать биссектрису каждого угла (легко рассчитать с помощью трех последовательных вершин) в полигоне и взять точку на этом биссектрере, которая станет вершиной для внутреннего многоугольника. Затем я беру либо внешнюю многоугольную вершину, либо внутреннюю многоугольную вершину, чтобы построить массив вершин, который может соответствовать параметру GL_TRIANGLE_STRIP. Я поставил изображение ниже, чтобы понять лучше.

expl http://img571.imageshack.us/img571/892/convexpolyexplanation.png

+0

Просто замечание общего, но вы должны думать в терминах треугольников, а не произвольные многоугольники. – JasonD

ответ

2

Будет ободок освещения шейдер делать то, что вы хотите? Link to an example

Пример кода для 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); 
+0

Действительно интересно, я посмотрю на это:) – olma

+0

Я работаю над 2D-проектом, поэтому нет такого понятия глубины, и я полагаю, что значение float NormalToCam не имеет смысла в моем случае. Я сохраняю это для своих будущих 3D-проектов;) – olma

+0

Ну, у вас все еще есть понятие глубины! Все просто имеет одну и ту же глубину. Интересно, можете ли вы сделать нормали вдоль внешней полифонии, ортогональной к камере, и нормали на внутренней точке, параллельной камере. Это может заставить вас работать на вас. В любом случае я ПОДОЗРЕВАЮ, техника может быть адаптирована как-то. – MrLeap

1

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

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

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

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

  4. glDisable(GL_BLEND); 
    
+0

На самом деле это 2D-проект, но ваш метод подтверждает мои, и я думаю, что это должно сработать. Thx;) – olma

+0

Нет проблем! Я так привык думать в 3d-пространстве, что просто забыл, что люди использовали OpenGL для 2D-чертежа. Удачи! –

 Смежные вопросы

  • Нет связанных вопросов^_^