Eu tenho trabalhado em um jogo de peças 2D e implementei iluminação com arestas:
Eu quero que seja suavizado um pouco. Não preciso de sombras nem nada, apenas iluminação simples. Eu gostaria que parecesse mais com isso:
Meu sistema atual usa níveis de luz para cada bloco do mundo e eles são recalculados quando um bloco é colocado ou removido. Estou usando batch.setColor(...)
para sombrear os azulejos. Qual é uma boa maneira de obter essa iluminação suave?
Não quero usar o método de sobreposição de mapas leves, já tentei e não fiquei satisfeito com o resultado. Quero poder definir quanta luz é capaz de passar através de um bloco. Por exemplo, um bloco de terra deve absorver um pouco da luz, mas um bloco de vidro não deve bloquear nenhuma luz. Isso não era realmente possível com o método de sobreposição do mapa de luz. UPDATE: Eu não entendi o que esse método realmente é. Eu entendo agora. Eu estava pensando da maneira errada. Desculpa!
Respostas:
Uma maneira simples de obter uma iluminação suave em um jogo baseado em blocos é desenhar um "mapa de luz" para um alvo de renderização e, em seguida, desenhar esse alvo de renderização por cima de sua cena enquanto o alfa é misturado.
O destino de renderização do seu mapa claro seria do tamanho do seu mapa de blocos, mas em pixels. Cada pixel representaria a cor clara de seu bloco correspondente. Essa textura de renderização ficaria assim: (textura superior esquerda em preto e branco):
Depois de ter essa textura leve do mapa, você pode desenhá-la como uma sobreposição no seu mundo de jogo (estendido). Você terá que prendê-lo adequadamente, para que ele se estenda perfeitamente sobre suas peças no mundo do jogo.
Então é uma questão de alfa misturar essa textura no seu mundo de jogo no libGDX. Para se misturar ao LibGDX (eu pessoalmente não sei como), você pode precisar examinar a
Gdx.gl.glBlendFunc
função.fonte
Uma maneira independente de fazer isso é usar o mapeamento médio da luz. Primeiro, você precisa gerar um mapa em preto e branco como uma matriz 2D de booleanos que é do tamanho do mundo em que os blocos são True e vazios são False.
Assim (1 é preto, 0 é branco):
Em seguida, você precisa criar uma nova matriz 2D que tenha o mesmo tamanho da primeira matriz, mas que seja uma matriz de flutuadores. Depois, você passa do bloco preto (True) para o bloco preto na matriz e calcula a média do valor amostrado próximo (explicado abaixo)
Esta imagem ajudará:
Esta imagem representa a amostragem (onde + significa falso e | significa verdadeiro). o que fazemos é tratar valores verdadeiros como 1 e valores falsos como 0. Então você calcula a média dos 9 números e os coloca na parte correta da matriz. NOTA: Certifique-se de que, quando estiver amostrando arestas, use valores externos como sensíveis ao contexto. Por exemplo: no subsolo o mapa fora do mundo pode ser 1 e o céu deve ser 0.
Deve ficar assim (tirado de outra postagem):
Então tudo o que você precisa fazer é colorir cada bloco na matriz com
(matiz = o valor médio atual do bloco na segunda matriz e alfa não importa). Nota: isto pressupõe que a pseudo-função rgba recebe flutuadores de 0-1 em vez de 0-255, se o fizer, faça o seguinte:
Espero que isso faça um pouco de sentido :) Se você quiser código, pergunte!
fonte
Como você está falando sobre coisas bloqueando a luz, suponho que você tenha algum modelo de como a luz deve se espalhar. Por exemplo, tudo sem blocos acima está completamente aceso, a luz se espalha para todas as células vizinhas, mas perde uma certa quantidade de brilho.
Você deve ser capaz de implementar essas regras com bastante facilidade no lado do software, pelo menos a parte de suavização é apenas uma questão de jogar shader no mapa de luz que você gerou.
Os métodos sugeridos por outras pessoas sobrepondo um mapa claro é algo que você deve fazer de qualquer maneira. Mas você pode mudar a forma como gera esse mapa de luz. Inicialmente, você pode preenchê-lo apenas com as informações do bloco, mas pode escaloná-lo e suavizá-lo em um sombreador, por exemplo. Um benefício adicional da abordagem do mapa de luzes é que você pode simplesmente atrair luzes dinâmicas para o seu mapa de luzes, assim como destacar as explosões ou o que você tem e ele naturalmente se misturará com o resto do seu mundo.
Aditivo mistura coisas em seu mapa de luz, em seguida, multiplicativo mistura seu mapa de luz com o mundo do jogo.
Eu fiz isso há um tempo atrás, que usa os mesmos princípios. Este sistema não suporta ter queda de luz diferente para diferentes tipos de terreno, mas pelo menos deve ilustrar a utilidade de sobrepor um mapa de luz.
fonte
É muito fácil para uma tocha: usando um sombreador de pixel personalizado, você calcula a distância entre cada fragmento e a tocha; você pode calcular onde o primeiro bloco denso que bloqueia a luz proveniente da tocha. Em seguida, você calcula a distância em que a luz não está bloqueada, multiplique por algo <1 para que a tocha não acenda o sol, subtraia-o da distância total e repita o restante da distância (onde a luz foi bloqueada por menos um bloco) com um valor multiplicado bem menor ... Eu sei como fazer essa matemática e não é muito complicado de implementar em opengl.
EDIT: para uma fonte de luz simples com um ponto central específico, meu método é extremamente simples. No entanto, o meu não funciona com a luz do sol, mas, embora o mapa alfa funcione muito bem para a luz do sol, NÃO seria uma boa idéia para uma tocha, uma vez que é potencialmente um objeto em movimento, e fazer um novo mapa a cada quadro não é agradável. experiência de vida. A melhor solução na minha opinião é uma mistura: cálculo da distância para luzes específicas que são realmente objetos no jogo, um sombreador separado que você coloca no topo do mapa alfa que você gerou processualmente usando a técnica mencionada acima: uma textura de tudo os azulejos alfas do seu sombreamento rígido, como muitos quadrados, e mexem com técnicas para suavizá-lo.
fonte
Sua renderização usa cores de vértice (ou você pode alterá-la)?
Supondo que cada bloco seja um quadrado de 4 vértices, você daria algumas opções, por exemplo:
Se o seu algoritmo de iluminação atual fornecer um valor de luz por bloco, você poderá alterá-lo para fornecer um valor por vértice. Como alternativa, em cada vértice você pode calcular a média da cor clara do bloco atual mais seus três vizinhos. Qualquer solução seria barata.
fonte