GLSL- ¿Cómo cambiar un cierto color de un sprite, a otro color que pasa al sombreador?

Hay sprites, con ciertos píxeles que son de color rosa shiny, y un sombreador tiñe estos píxeles rosados ​​o en escala de grises a un color personalizado determinado por el jugador. Por ejemplo, un personaje parece normal a exception de su cinturón de karate, que está teñido según el nivel del jugador (una variable fuera del sombreador que cambia el color del cinturón a lo largo del juego).

Estoy buscando no tener que usar otra textura como máscara, porque eso es mucho trabajo adicional para todos los cuadros de animation de cada personaje.

Algo como esto:

originalFaceColor -> newFaceColor

OriginalShirtColor -> newShirtColor

originalHairColor -> newHairColor

Sé cómo hacer esto en el código para editar la textura y crear una nueva:

getPixel (); if (color) setPixel (newColor);

pero preferiría usar un sombreador porque todos los personajes compartirán exactamente la misma image, pero me gustaría que cada personaje tenga colors únicos.

Puede usar un sombreador simple para esto, pero yo no lo haría, simplemente porque está haciendo un tinte simple con un color (o tonos de un solo color). La secuencia de commands de Unity anterior funcionaría con algunas modificaciones, pero tendrá que tener en count que hay gastos indirectos / metadatos adicionales que no pertenecen al código GLSL real.

Lo que haría es dividir la textura en function de las áreas tintables / no tintables y luego dibujar en dos pasadas:

  • Un pase representarás la parte no tintada de la textura.
  • En otra pasada, representará la parte tintada de la textura utilizando sf::Sprite::setColor() para establecer el color real.

Si bien esto podría ser less eficiente que usar un sombreador, obtendrá una compatibilidad mucho mejor con esto (por ejemplo, los puertos mobilees de SFML no son compatibles con los sombreadores hasta el momento). Además de eso, no tendrá que codificar múltiples verificaciones / valores / swaps de colors (que de hecho no lo hará, ya que es mejor hacerlo programáticamente).

Personalmente, he utilizado esta estrategia en el pasado con la siguiente textura:

Textura de ejemplo

Es una hoja de sprite simple de un tipo corriendo hacia la derecha (cuatro cuadros de animation).

Mientras que la primera fila incluye los sprites completos que se teñirán, la segunda fila contiene las áreas no teñidas.

Para dibujar uno de esos personajes, estoy usando dos sprites. Sprite one usa la primera fila de la textura y sf::Sprite::setColor() para dibujar ropa de color. El segundo elemento se dibuja en la parte superior sin tintado para dibujar las manos y la cara con sus colors originales.


Si realmente quieres hacer esto en un sombreado, evitaría la bifurcación if () ya que eso puede ralentizar tu código. También es bastante tedioso actualizar el código o trabajar con múltiples sombras (lo cual es mucho más fácil de hacer con el enfoque de tinte). Entonces, en cambio, podrías usar una textura 1D de 256 píxeles de ancho. Simplemente tendría que comprobar el color de un píxel de pantalla y, en caso de que los tres componentes sean idénticos (o solo rojo y cian y verde sea 0), usaría ese valor como índice en la textura 1D para get el color de reemploop.