Como mesclar os círculos de seleção de unidades?

16

Gostaria de saber como fazer esse efeito da seleção de círculos mesclados. Aqui estão imagens para ilustrar:

insira a descrição da imagem aqui insira a descrição da imagem aqui

Basicamente, estou procurando esse efeito:

insira a descrição da imagem aqui

Como o efeito de mesclagem dos círculos pode ser alcançado? Não encontrei nenhuma explicação sobre esse efeito. Sei que para projetar essas texturas, posso desenvolver um sistema de decalques, mas não sei como criar o efeito de mesclagem.

Se possível, estou procurando uma solução puramente shaders.

Esteira
fonte
Você poderia explicar o que você quer dizer com "efeito de mesclagem"?
Wondra
Obviamente, se você olhar para os caracteres superior direito da captura de tela, os decalques não se cruzam, mas os dois à esquerda cruzam seu círculo azul e são mesclados. Eu adicionei uma nova captura de tela para mostrar o efeito.
MAT
Você insiste em solução shader? Caso contrário, você acabou de resolver na sua última foto.
Wondra
A última captura de tela mostra apenas o efeito que estou direcionando. O resultado final deve se parecer com as capturas de tela anteriores.
MAT
1
Sim, eu concordo, acho que eles constroem dinamicamente um círculo de malha com a textura e depois cortam a malha para mesclá-los. Também é uma boa solução, mas acho que é mais limitada em termos de efeito que você pode fazer.
MaT

Respostas:

8

Existem alguns truques que você pode fazer:

Z-buffer

Depois de renderizar todos os outros objetos, para cada unidade, renderize um círculo transparente de tamanho menor com o valor máximo de Z. Em seguida, renderize os decalques dos círculos de seleção no chão. Como estão abaixo na ordem Z, serão descartados quando estiverem em unidades.

Ser totalmente transparente significa que o círculo é gravado apenas no buffer Z (valor Z máximo). Agora, quando você renderiza decalques, eles são testados em relação aos valores do buffer Z e, se passam no teste, são renderizados (o que acontece apenas fora dos círculos)

Estêncil

O mesmo da abordagem anterior, mas desta vez use um buffer de estêncil. Renderize círculos menores para unidades com algum valor de estêncil e, em seguida, renderize decalques de seleção. Configure o estêncil para descartar quaisquer elementos com seu valor de estêncil.

Kromster diz apoio Monica
fonte
A técnica do Z-Buffer é interessante, mas não entendo como o primeiro círculo transparente pode cortar os decalques do solo.
MaT
0

Você pode, por exemplo, verificar o sombreamento de pixel de renderização de decalques se houver uma interseção com outros decalques e, se houver, eliminar o pixel. É bastante eficiente fazer esse tipo de adesivo circular.

JarkkoL
fonte
1
Suponho que você tenha pulado a parte da sua resposta - para passar todos os locais e raios dos círculos para sombreamento.
Kromster diz apoio Monica
@Krom Se a OP manifestar interesse na solução, fico feliz em fornecer mais detalhes.
JarkkoL
0

Você quer dizer aqueles círculos azuis no chão?

Pode haver uma maneira mais inteligente de fazer isso, mas considere minha solução como um exemplo de como isso pode ser feito. Renderize seus círculos para uma textura vazia separada do tamanho da tela. Neste ponto, você pode misturá-los, como quiser. Dependendo das suas necessidades, você pode escrever a cor completa ou apenas as informações de que um círculo está presente em determinado pixel. No entanto, você definitivamente precisará de informações detalhadas para cada pixel que escrever, se desejar um efeito de teste Z.

Ao renderizar o terreno após a etapa anterior, você pode experimentar a textura criada anteriormente, usando as coordenadas da tela no sombreador de pixels, como UVs. Agora você sabe que o círculo deve ou não ser projetado em determinado pixel do terreno. No entanto, dessa maneira, ele funcionará como se o teste Z estivesse desabilitado, portanto, um terreno não pode ocultar nenhum círculo. Se você deseja que um terreno oculte círculos que estão atrás dele, faça um teste de profundidade antes de misturar um círculo com a textura do terreno. Você pode usar um pequeno viés para ativar a renderização de círculos que estão um pouco abaixo do terreno, mas você ainda gostaria que eles renderizassem.


Editar: Agora, para obter o efeito de círculos mesclados, o que você precisa fazer é: Ao renderizar para a textura separada, é necessário verificar se já existe um círculo renderizado no qual você está tentando renderizar um novo. (Verifique se a textura possui um valor). Se houver, apague esse pixel. Isso deve dar o efeito de "estrutura de tópicos" quando dois ou mais círculos se sobrepõem. Para que isso funcione corretamente, você precisará fazer esse teste apenas para o interior do círculo, não para a borda. Portanto, ao renderizar círculos, escreva algum valor específico na textura de saída, o que indica que é um círculo dentro. Então você não precisa renderizar nada no círculo interno e deve ser bom.

Edit2: Para seu exemplo simples de vermelho / verde: Antes de renderizar qualquer pixel, verifique se esse pixel ainda não está verde. Se for, não processe. Isto irá fazer o truque. De fato, ao escrever na textura, você pode usar vermelho / verde para fora / dentro do círculo e, ao renderizar o terreno, leia esses valores e os converta na cor desejada.

Se minha resposta for muito abstrata por acaso, me avise.

Elvithari
fonte
Tenho a ideia geral, mas como você diz, é um pouco de abstrair para mim sobre os círculos incorporadas :)
MAT
0

Existem algumas opções. Como método geral, os buffers de estêncil costumam ser muito úteis onde certos desenhos precisam ser mascarados, como o contorno em que os círculos se sobrepõem no seu exemplo.

Nesse caso, acho que isso pode ser feito com a mesma facilidade, sem um buffer de estêncil. Você pode usar o buffer de profundidade para eliminar o contorno onde os círculos se sobrepõem. A idéia é que você desenhe o interior dos círculos apenas no buffer de profundidade (já que não queremos ver o interior) e desenhe o contorno. Dessa forma, a parte do contorno que se sobrepõe a outro círculo será eliminada pelo teste de profundidade.

A única ressalva é que você deve ter cuidado com os combates em profundidade. Você pode usar um pequeno deslocamento para garantir que os contornos estejam realmente atrás do interior e serem eliminados pelo teste de profundidade. Uma alternativa seria usar glPolygonOffset().

Digamos que você tenha dois círculos paralelos ao plano xy, com centros em (x1, y1, z) e (x2, y2, z). E você tem estas funções de desenho:

// Draw interior part of circle, shown in green in the schematic in the question.
drawInterior(x, y, z);

// Draw outline of circle, shown in red in the schematic in the question.
drawOutline(x, y, z);

A sequência de desenho fica assim, com deltaum pequeno deslocamento:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
drawInterior(x1, y1, z + delta);
drawInterior(x2, y2, z + delta);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawOutline(x1, y1, z);
drawOutline(x2, y2, z);

fonte
0

Do alto da minha cabeça, se esses decalques forem desenhados como discos, eu testaria cada círculo em busca de interseção uns contra os outros e colocaria os pontos de interseção em uma matriz. Em seguida, desenhe arcos que não estão dentro de uma interseção. Esta não é uma solução shader, no entanto.

melfar
fonte
Sim, eu pensei nisso também :) mas como você disse, não é uma solução de sombreador e não é uma solução muito genérica. Mas obrigada!
14282 MaT
Essa é uma descrição bastante vaga
Kromster diz apoio Monica
0

Você quer escrever aqui. Seu primeiro passe renderiza os círculos no buffer de estêncil. A segunda passagem renderiza o contorno visível , em qualquer lugar em que o buffer do estêncil não tenha sido alterado. A segunda passagem deve usar geometria maior que a primeira, neste caso, um escalar linear simples é suficiente.

Embora a solução que eu tenho para desenhar contornos aqui seja mais do que você precisa (como esse sombreador transforma todas as arestas de malha em um quad completo), ele segue esta abordagem: desenhar o modelo original no buffer de estêncil e renderizar uma versão maior em que o buffer de estêncil ainda é 0.

Draco18s não confia mais no SE
fonte
Obrigado! Então, em vez de primeiro desenhar as partes visíveis, devo começar renderizando os círculos transparentes no estêncil. Mas como renderizo círculos transparentes redondos? Não posso limitar partes da imagem a serem renderizadas no estêncil. Quando renderizo para o estêncil, tudo vai lá, estou certo?
Doodlemeat 13/01/19
Sim, é por isso que a segunda passagem (a parte visível) é dimensionada para maior: para que seus limites sejam maiores que o buffer de estêncil. Você só precisa aplicar um escalar de vértice na segunda passagem (procure em volta shaders de contorno, a maioria deles usa o escalar mais simples ao qual estou me referindo). Você também não pode alterar o buffer de estêncil se a cor for transparente. Você provavelmente precisará de uma segunda máscara de textura nesse caso ou poderá fazer algumas cálculos à distância para determinar o círculo. Eu precisaria de algumas horas e acesso ao Unity para fornecer qualquer código.
Draco18s não confia mais em SE
Hmm, que tal ter uma imagem em preto e branco apenas para gravar no buffer de estêncil na primeira passagem, para que o preto se torne 0 e o branco se torne 1 no estêncil. É mesmo possível?
Doodlemeat
Isso foi o que quis dizer com uma segunda máscara de textura. Tenho certeza de que funcionaria, simplesmente não posso verificar sem ter o Unity na minha frente, o que não terei por mais de 24 horas.
Draco18s não confia mais em SE