Это не особо сложно. Вам просто нужно преобразовать координаты текстуры в полярные координаты и использовать радиус для направления текстуры s
и азимутальный угол в направлении t
.
Предположим, что вы хотите текстурировать квадрат таким образом, а также предполагая, что для этого вы используете стандартные texcoords, поэтому нижняя левая вершина будет иметь (0,0), верхний правый (1,1) в качестве текстурных коордов.
Итак, в фрагментном шейдере вам просто нужно преобразовать интерполированные texcoords (используя для этого tc
) в полярные координаты. SInce центр будет в (0,5, 0,5), мы должны сначала компенсировать это.
vec2 x=tc - vec2(0.5,0.5);
float radius=length(x);
float angle=atan(x.y, x.x);
Теперь все, что вам нужно сделать, это отобразить диапазон обратно в [0,1] пространство текстур. Максимальный радиус здесь будет 0,5, поэтому вы просто можете использовать 2*radius
как координату s
, а угол будет в [-pi, pi], поэтому вы должны сопоставить это значение с [0,1] для координаты t
.
Update1
Есть несколько деталей, я оставил так далеко. Из вашего изображения ясно, что вы не хотите, чтобы внутренний круг отображался на текстуру. Но это легко может быть отменено. Я просто предполагаю здесь два радиуса: r_inner
, который является радиусом внутреннего круга, и r_outer, который является радиусом, на который вы хотите отобразить внешнюю часть. Позвольте мне набросать простой фрагментный шейдер для этого:
#version ...
precision ...
varying vec2 tc; // texcoords from vertex shader
uniform sampler2D tex;
#define PI 3.14159265358979323844
void main()
{
const float r_inner=0.25;
const float t_outer=0.5;
vec2 x = v_tex - vec2(0.5);
float radius = length(x);
float angle = atan(x.y, x.x);
vec2 tc_polar; // the new polar texcoords
// map radius so that for r=r_inner -> 0 and r=r_outer -> 1
tc_polar.s = (radius - r_inner)/(r_outer - r_inner);
// map angle from [-PI,PI] to [0,1]
tc_polar.t = angle * 0.5/PI + 0.5;
// texture mapping
gl_FragColor = texture2D(tex, tc_polar);
}
Теперь все еще отсутствует одна деталь. Сгенерированное отображение генерирует texcords, которые находятся вне диапазона [0,1] для любой позиции, где у вас есть balck на вашем изображении. Но выборка текстуры не будет автоматически давать черный здесь. Самое простое решение - добавить черный пиксель на левом и правом конце текстуры и установить режим текстуры GL_TEXTURE_WRAP_S
на GL_CLAMP_TO_EDGE
. Таким образом, вы получите черный цвет почти бесплатно. Другим способом было бы добавить плечо в шейдер и проверить, что tc_polar.s
находится ниже 0 или выше 1.
Не могли бы вы предоставить полный код шейдера? – Nolesh
@ Nolesh: Я обновил свой ответ. – derhass
Знаете ли вы, как изменить этот шейдер, чтобы сделать результат из сегментов? Поэтому мне нужно повторить данную текстуру, а не растягиваться. – Nolesh