Pergunta

Perdoe-me se isso já foi perguntado antes, estive procurando a resposta para isso o dia todo e tudo que consegui é ajuda com jogos 2D baseados em blocos.x~x

Estou tentando criar uma GUI personalizável no Direct3D 9, usando um arquivo XML que possui posições para cada elemento e uma opção para esticá-los ou colocá-los lado a lado.O alongamento é um procedimento bastante simples, mas não consegui descobrir uma maneira de colocar lado a lado uma pequena seção de uma textura.Tradicionalmente, para colocar uma textura lado a lado, eu apenas definiria as coordenadas UV como > 1,0, mas as coordenadas da textura de origem serão apenas um pequeno subconjunto de toda a textura, como 0,4 a 0,5.

Tenho a sensação de que perdi algo realmente óbvio, mas como eu faria para simplesmente colocar lado a lado em vez de esticar?Meu melhor palpite é que tem algo a ver com ter mais de um conjunto de coordenadas de textura, mas a partir daí não tenho certeza para onde ir.

O projeto atualmente usa o pipeline de função fixa, então eu preferiria uma resposta usando isso, se possível, mas não recusaria uma resposta que usa um shader se essa for a única maneira.

Foi útil?

Solução

Entendo que você deseja colocar lado a lado apenas um subconjunto da textura, certo?Então as coisas ficam complicadas.

Suponha que queremos colocar a coordenada u entre os valores u1 e u2, u1 <u2.

Então precisamos de uma função f(u), tal que

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...

Uma função apropriada é f(u) = frac(u) * (u2-u1) + u1

O mesmo vale para v-coord, f(v) = frac(v) * (v2-v1) + v1

Observe que está lado a lado sem espelhamento.Se você precisar de espelhamento, então a função deverá ser uma função de onda triangular, que é t(x) = arcsin(sin(pi*(x-0.5)))/pi+0.5 e f(u) = t(u) * (u2-u1) + u1.Usar funções trigonométricas pode ser caro.

Não sei se é possível com pipeline fixo, mas você pode fazer isso facilmente no pixel shader (código 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);

ou

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

EDITAR:uma maneira melhor de calcular a função de onda triangular: t1(x) = abs(2(0.5x-floor(0.5x+0.5))) ou t2(x) = abs(2(frac(0.5x+0.5))-1) (não exatamente igual a t1, mas correto para números não negativos).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top