Как мне разместить часть текстуры в пространстве экрана?

StackOverflow https://stackoverflow.com//questions/9655524

Вопрос

Простите меня, если об этом спрашивали раньше, я весь день искал ответ на этот вопрос, и все, что я нашел, это помощь с 2D-играми на основе плиток.х~х

Я пытаюсь создать графический интерфейс пользователя с возможностью смены скинов в Direct3D 9, используя XML-файл, в котором есть позиции для каждого элемента и возможность их растягивания или мозаики.Растяжение — достаточно простая процедура, но мне не удалось придумать, как замостить небольшой участок текстуры.Традиционно для мозаики текстуры я бы просто установил UV-координаты > 1,0, но координаты исходной текстуры будут лишь небольшим подмножеством всей текстуры, например, от 0,4 до 0,5.

У меня такое чувство, что я пропустил что-то действительно очевидное, но как мне просто замостить вместо растягивания?Я предполагаю, что это как-то связано с наличием более одного набора координат текстуры, но я не уверен, куда идти дальше.

В настоящее время в проекте используется конвейер с фиксированными функциями, поэтому я бы предпочел, чтобы ответ использовал его, если это возможно, но я бы не отказался от ответа, использующего шейдер, если это единственный способ.

Это было полезно?

Решение

Я понимаю, что вы хотите замостить только часть текстуры, верно?Тогда все усложняется.

Предположим, мы хотим разместить координату u между значениями u1 и u2, u1 < u2.

Тогда нам нужна функция f(u), такая, что

f(0.0) = u1
f(0.5) = (u1+u2)/2
f(0.9999) = u2
f(1.0) = u1
f(1.5) = (u1+u2)/2
f(1.9999) = u2
f(2.0) = u1
and so on...

Соответствующая функция f(u) = frac(u) * (u2-u1) + u1

То же самое касается v-координаты, f(v) = frac(v) * (v2-v1) + v1

Обратите внимание, что это мозаика без зеркалирования.Если вам нужно зеркальное отображение, то функция должна быть функцией треугольной волны, которая t(x) = arcsin(sin(pi*(x-0.5)))/pi+0.5 и f(u) = t(u) * (u2-u1) + u1.Однако использование тригонометрических функций может быть дорогостоящим.

Я не знаю, возможно ли это с фиксированным конвейером, но вы можете легко сделать это в пиксельном шейдере (код HLSL):

// float2 tex_coord -> (u,v) from vertex shader, in [0,n] range,
//                     n - number of repetitions
// float2 tex1, tex2 -> constants, subrange of [0,1] coords that will be tiled

// no mirroring
float4 color = tex2D(sampler, frac(tex_coord) * (tex2-tex1) + tex1);

или

// mirroring, t(x) = arcsin(sin(pi*(x-0.5)))/pi+0.5
float4 color = tex2D(sampler, t(tex_coord) * (tex2-tex1) + tex1);

РЕДАКТИРОВАТЬ:лучший способ вычисления функции треугольной волны: t1(x) = abs(2(0.5x-floor(0.5x+0.5))) или t2(x) = abs(2(frac(0.5x+0.5))-1) (не совсем то же самое, что t1, но с поправкой на неотрицательные числа).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top