2010-11-29 6 views
11

Я искал способ, чтобы нарисовать что-то похожее на эти «ручки» с GLSL шейдерOPENGL GLSL Shader: Нарисуйте круг на плоский многоугольник

alt text

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

ответ

8

Да, это возможно! Проверьте этот GLSL скрипт, который рисует несколько различных дуг:


#define between(v,x1,x2) (v>= x1 && v<=x2) 
#define pi 3.141592653589793238462643383279 

uniform sampler2D tex; 

void main() 
{ 
    vec2 pnt = vec2(0.5,0.5); 
    float dr = 0.005; 
    float fr = 0.15; 
    float r1 = fr; 
    float r2 = 1.5*fr; 
    float r3 = 2.0*fr; 
    float r4 = 2.5*fr; 
    float r5 = 3.0*fr; 
    float rp = distance(pnt,gl_TexCoord[0].xy); 
    vec4 col1 = vec4(0.4,0.1,0.,1.); 
    vec4 col2 = vec4(1.,1.,1.,1.); 
    float angle = atan(gl_TexCoord[0].y,gl_TexCoord[0].x); 
    vec4 rezcol; 
    rezcol = (between(rp,r1-dr,r1+dr) && between(angle,-pi,pi))? col1:col2; 
    rezcol = (between(rp,r2-dr,r2+dr) && between(angle,-pi,pi/3.1) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r3-dr,r3+dr) && between(angle,-pi,pi/4.6) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r4-dr,r4+dr) && between(angle,-pi,pi/8.8) && rezcol==col2)? col1:rezcol; 
    rezcol = (between(rp,r5-dr,r5+dr) && between(angle,-pi,pi/22.8) && rezcol==col2)? col1:rezcol; 
    gl_FragColor = rezcol; 
} 

что приводит к такому изображению:

alt text

+0

Не самый элегантный подход всего, я бы сказал;) Вводите одну ветвь (? :) за круг, чего можно избежать. Кроме того, может быть расширен с некоторым сглаживанием. (Тем не менее, +1) – Kos 2010-12-01 16:47:01

11

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

Если вы хотите покрасить только дугу, получите угол с atan (y, x) и проверьте, находится ли он в заданном диапазоне.

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

Также в качестве оптимизации вам не нужно вычислять квадратный корень при расчете расстояния до центра, если вы вместо этого проверяете радиус^2.

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