He estado trabajando en un juego de fichas 2D y he implementado una iluminación de bordes duros:
Quiero que se suavice un poco. No necesito sombras ni nada, solo iluminación simple. Me gustaría que se parezca más a esto:
Mi sistema actual utiliza niveles de luz para cada mosaico en el mundo y se recalculan cuando se coloca o elimina un mosaico. Estoy usando batch.setColor(...)
para sombrear los azulejos. ¿Cuál es una buena manera de lograr esta iluminación suave?
No quiero usar el método de superposición de mapas claros, ya lo intenté y no estaba contento con el resultado. Quiero poder establecer cuánta luz puede pasar a través de un bloque. Por ejemplo, un bloque de tierra debería absorber algo de la luz, pero un bloque de vidrio no debería bloquear ninguna luz. Esto no fue realmente posible con el método de superposición de mapa de luz. ACTUALIZACIÓN: no entendí qué es realmente este método. Entiendo ahora. Estaba pensando en el camino equivocado. ¡Lo siento!
Respuestas:
Una forma simple de lograr una iluminación suave en un juego basado en fichas es dibujar un "mapa de luz" en un objetivo de renderizado y luego dibujar este objetivo de renderizado sobre la escena mientras se mezcla alfa.
El objetivo de representación de su mapa de luz sería del tamaño de su mapa de mosaico, pero en píxeles. Cada píxel representaría el color claro de su mosaico correspondiente. Esta textura de renderizado se vería así (textura superior izquierda en blanco y negro):
Una vez que tenga esta textura ligera del mapa, puede dibujarla como una superposición sobre su mundo de juego (extendido). Tendrás que sujetarlo correctamente, para que se extienda perfectamente sobre tus fichas en el mundo del juego.
Entonces es una cuestión de alfa mezclar esta textura en su mundo de juego en libGDX. Para combinar LibGDX (personalmente no sé cómo), es posible que tenga que mirar la
Gdx.gl.glBlendFunc
función.fuente
Una forma agnóstica del motor para hacerlo es utilizar el mapeo de luz promedio. Primero, debe generar un mapa en blanco y negro como una matriz 2D de booleanos del tamaño del mundo donde los bloques son Verdaderos y los vacíos es Falso.
Así (1 es negro, 0 es blanco):
Luego, debe crear una nueva matriz 2D que tenga el mismo tamaño que la primera matriz pero que sea una matriz de flotadores. Luego pasa del bloque negro (Verdadero) al bloque negro en la matriz y promedia el valor muestreado cercano (explicado a continuación)
Esta imagen ayudará:
Esta imagen representa el muestreo (donde + significa falso y | significa verdadero). lo que hacemos es tratar los valores verdaderos como 1 y los valores falsos como 0. Luego, promedia los 9 números y los coloca en la parte correcta de la matriz. NOTA: Asegúrese de que cuando muestrea aristas utilice los valores externos como sensibles al contexto. Por ejemplo: bajo tierra, el mapa fuera del mundo podría ser 1 y el cielo debería ser 0.
Debería verse así (tomado de otra publicación):
Entonces, todo lo que tiene que hacer es teñir cada bloque de la matriz con
(tint = el valor de bloque promedio actual en la segunda matriz y alfa no importa). Nota: esto supone que la pseudofunción rgba toma flotantes de 0-1 en lugar de 0-255, si es así, simplemente haga esto:
Espero que esto tenga un poco de sentido :) Si quieres código, por favor pregunte!
fuente
Como estás hablando de cosas que bloquean la luz, supongo que tienes algún modelo de cómo debería extenderse la luz. Por ejemplo, todo lo que no tiene bloques encima está completamente iluminado, la luz se extiende a todas las celdas vecinas pero pierde una cierta cantidad de brillo.
Debería poder implementar esas reglas con bastante facilidad en el lado del software, al menos la parte de suavizado es solo una cuestión de arrojar algo de sombreador en el mapa de luz que ha generado.
Los métodos que otros han sugerido para superponer un mapa de luz es algo que debe hacer de todos modos. Pero puede cambiar cómo genera este mapa de luz. Inicialmente puede llenarlo solo con la información del bloque, pero luego puede escalarlo y suavizarlo en un sombreador, por ejemplo. Un beneficio adicional del enfoque del mapa de luz es que simplemente puede dibujar luces dinámicas en su mapa de luz para resaltar explosiones o lo que sea que tenga, y naturalmente se combinará con el resto de su mundo.
Aditivo mezcla cosas en tu mapa de luz y luego multiplicativa mezcla tu mapa de luz con el mundo del juego.
Hice esto hace un tiempo que usa los mismos principios. Este sistema no admite que la caída de luz sea diferente para diferentes tipos de terreno, pero al menos debería ilustrar la utilidad de superponer un mapa de luz.
fuente
Es bastante fácil para una antorcha: usando un sombreador de píxeles personalizado, calcula la distancia entre cada fragmento y la antorcha; A continuación, puede calcular dónde está el primer mosaico denso que bloquea la luz que proviene de la antorcha. Luego calcula la distancia donde la luz no está bloqueada, multiplique eso por algo <1 para que la antorcha no encienda el sol, reste eso de la distancia total y repita por el resto de la distancia (donde la luz fue bloqueada por menos un mosaico) con un valor de multiplicación mucho más pequeño ... Sé cómo hacer esta matemática y no es demasiado complicado de implementar en opengl.
EDITAR: para una fuente de luz simple con un punto central específico, mi método es extremadamente simple. Sin embargo, el mío no funciona con la luz solar, pero si bien el mapa alfa funciona muy bien para la luz solar, NO sería una buena idea para una antorcha, dado que es potencialmente un objeto en movimiento, y hacer un nuevo mapa en cada cuadro no es agradable. experiencia de vida. La mejor solución en mi opinión es una combinación: cálculo de distancia para luces específicas que en realidad son objetos en el juego, un sombreador separado que simplemente arrojas sobre el mapa alfa que generaste procesalmente usando la técnica mencionada anteriormente: una textura de todos los mosaicos alfa de tu sombreado duro, como muchos cuadrados, y desordenar con técnicas para suavizarlo.
fuente
¿Su renderizado usa colores de vértice (o puede cambiarlo)?
Suponiendo que cada bloque es un cuadrado de 4 vértices, eso le daría un par de opciones, por ejemplo:
Si su algoritmo de iluminación actual le da un valor de luz por bloque, puede cambiarlo para obtener un valor por vértice. Alternativamente, en cada vértice puede promediar el color de la luz del bloque actual más sus tres vecinos. Cualquiera de las soluciones sería económica.
fuente