OpenGL GLSL Shader: Нарисуйте круг на плоском полигоне

Я ищу способ нарисовать что-то похожее на эти "ручки" с помощью шейдера GLSL

alt text

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

Ответ 1

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


#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

Ответ 2

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

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

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

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