Desenfoque de imagen de fondo de la unidad



Una de las tareas que puede encontrar un desarrollador de aplicaciones de Unity es poner la imagen actual en segundo plano para cambiar la atenci贸n del usuario a algo nuevo, como un men煤 o mensaje que aparece. El art铆culo habla sobre la experiencia de resolver este problema por un desarrollador que tiene conocimientos b谩sicos en Unity, sin usar recursos externos o una licencia adicional de Unity. Espero que este material sea 煤til para quienes enfrentaron un problema similar y no encontraron soluciones efectivas en las diferentes etapas del mismo.

Destacar elementos importantes de la interfaz (y eliminar los innecesarios) es una de las principales herramientas para mejorar la experiencia del usuario. Esto es especialmente pronunciado cuando se trabaja con aplicaciones m贸viles. Este cambio de atenci贸n se puede hacer de diferentes maneras: eliminando suavemente los botones m谩s all谩 de los bordes de la pantalla, oscureciendo el fondo, el comportamiento din谩mico, etc. Esto incluye desenfocar la imagen. Este efecto, por un lado, reduce el contraste de los elementos de fondo y hace que sea m谩s dif铆cil de captar. Por otro lado, el desenfoque tiene un efecto subconsciente cuando la imagen se desenfoca y la percibimos de manera diferente. Este enfoque se usa a menudo en juegos, y de ejemplos bien conocidos de juegos en Unity, podemos nombrar los momentos al elegir el men煤 de misiones de Hearthstone o enpantalla de finalizaci贸n de duelo .

Ahora imagine que queremos hacer lo mismo o similar en nuestra aplicaci贸n favorita. Tampoco estamos sin presupuesto y tenemos poca experiencia con Unity.

Primera parte - Shader


El primer pensamiento que surgi贸 fue que todo ya deber铆a estar realizado. Seguramente usando un sombreador. Y ciertamente deber铆a estar en el cuadro Unidad. Una b煤squeda r谩pida y un intento de instalaci贸n mostraron que existe un sombreador en Unity, pero resulta que es parte de los Activos est谩ndar y no est谩 disponible para una licencia gratuita.

Pero esto es borroso! Un efecto b谩sico que es matem谩ticamente simple y que tambi茅n debe implementarse e integrarse f谩cilmente en el proyecto. Incluso si no sabemos nada sobre sombreadores. A continuaci贸n, vaya a Internet y la b煤squeda mostr贸 r谩pidamente que existen c贸digos fuente de sombreadores ya preparados para el efecto, e incluso diferentes.

Para la primera implementaci贸n, se tom贸 este sombreador . Para probarlo, simplemente agregue el sombreador como un archivo fuente al proyecto, as贸cielo con el material, enlace el material a la imagen.

Segunda parte: interfaz de usuario


Si nos preocupamos por el usuario de la aplicaci贸n, entonces es necesario prestar la debida atenci贸n a la interfaz de usuario. Si solo agrega un efecto de desenfoque al fondo y lo olvida, entonces esto no es todo coherente con los principios internos de la creaci贸n de un producto.

Como resultado, para acciones adicionales, debe tocar lo que sucedi贸, y luego pensar y ajustar de tal manera que cause la percepci贸n necesaria del usuario. Este punto es altamente sensible al contexto. Dependiendo del contraste de la imagen, la variedad de colores y otros factores, se pueden seleccionar varios valores y herramientas adicionales. En nuestro caso, en esta etapa, se obtuvo un buen resultado con un radio de desenfoque de 25 (par谩metro de sombreador) y un Transparente adicional del 70% (fuera del sombreador a trav茅s de una Imagen separada). Sin embargo, esta es solo la imagen de fondo final. La transici贸n en s铆, seg煤n los sentimientos en el tel茅fono, fue demasiado aguda.

El sombreador instalado en la imagen se calcula en cada cuadro y, por lo tanto, para realizar un cambio suave, es suficiente cambiar din谩micamente el par谩metro del radio de desenfoque y la transparencia. Puede organizar esto de diferentes maneras, pero en esencia, el procesamiento es una actualizaci贸n en los controladores de actualizaci贸n, seg煤n la hora. La transici贸n en s铆 en la versi贸n final de la aplicaci贸n es de 0.2 segundos, pero resulta que es importante para la percepci贸n del usuario.

Tercera parte - Productividad


En los 煤ltimos meses, he escuchado quejas de varios usuarios diferentes (ni siquiera programadores) de que los programas de juegos a menudo usan todos los recursos inform谩ticos disponibles inactivos y sin frenos. Por ejemplo, esto se puede expresar en el uso m谩ximo de la tarjeta de video en el caso de un programa minimizado en la bandeja, o independientemente de todo y la carga constante de un subproceso del procesador. Las razones para esto son intuitivamente claras: los ingresos del desarrollador o editor no dependen de la optimizaci贸n (las personas no prestan atenci贸n a tales cosas cuando compran), y los desarrolladores comunes est谩n m谩s preocupados por los KPI locales y la necesidad de retrasar los plazos. Sin embargo, en la pr谩ctica, no me gustar铆a entrar en esta categor铆a.

Despu茅s de completar la etapa anterior en el pr贸ximo lanzamiento con un efecto de desenfoque de fondo, despu茅s de sostener el tel茅fono en la mano durante un tiempo, apareci贸 una sensaci贸n de calentamiento. Si pasa m谩s tiempo en el men煤, todo se vuelve mucho peor. E incluso si el usuario en el men煤 presumiblemente y lo m谩s probable es que no pase mucho tiempo, entonces no me gustar铆a dejar caer la bater铆a.

El an谩lisis mostr贸 que el sombreador elegido anteriormente tiene una complejidad asint贸tica O (r 2 ) dependiendo del radio seleccionado. En otras palabras, el n煤mero de c谩lculos por punto se vuelve 625 veces mayor si aumenta el radio de desenfoque de 1 a 25. En este caso, los c谩lculos se producen en cada cuadro.

El primer paso en la soluci贸n fue la idea de que no todos los sombreadores son igualmente 煤tiles, y el efecto de desenfoque se puede implementar de diferentes maneras. Para hacer esto, puede tomar un desenfoque separado, cuya esencia es desenfocar primero solo las l铆neas horizontalmente y luego solo las l铆neas verticalmente. Como resultado, obtenemos O (r) , y ceteris paribus la complejidad cae en un orden de magnitud. Una forma adicional ser铆a tomar un mipmap m谩s peque帽o, que ya toma parte del trabajo de desenfoque. Este sombreador

fue tomado como base. Sin embargo, su efecto de desenfoque result贸 ser insuficiente, y con un alto contraste del gr谩fico, la imagen se "astill贸". Para obtener mejores efectos, se ha cambiado la distribuci贸n (elementos GRABPIXEL). Si en el sombreador, de 0.18 a 0.05, radio 4, en nuestra versi贸n, de 0.14 a 0.03, radio 6 (ess, pero la suma de todos deber铆a ser 1).

Por lo tanto, la complejidad del procesamiento se redujo en 1-2 贸rdenes de magnitud. Pero esto no es necesario parar.

Cuarta parte: fondo est谩tico


Sin embargo, si dejamos el sombreador en la imagen existente, entonces est谩 constantemente trabajando, haciendo los mismos c谩lculos en cada cuadro. Si algo sucede en el fondo, entonces debemos hacerlo. Pero esto es completamente opcional si el fondo es est谩tico. Por lo tanto, despu茅s del desenfoque din谩mico, puede recordar el resultado, ponerlo en el fondo y apagar el sombreador.

A continuaci贸n, intentemos con fragmentos de c贸digo. La preparaci贸n de la textura de destino para toda la pantalla puede verse as铆:

_width = Screen.width / 2;
_height = Screen.height / 2;
_texture = new Texture2D(_width, _height);

var fillColor = Color.white;
var fillColorArray = _texture.GetPixels();
for (var i = 0; i < fillColorArray.Length; ++i)
{
	fillColorArray[i] = fillColor;
}
_texture.SetPixels(fillColorArray);
_texture.Apply();

_from.GetComponent<Image>().sprite = Sprite.Create(_texture, new Rect(0, 0, _texture.width, _texture.height), new Vector2(0.5f, 0.5f));

Es decir, aqu铆 se prepara una textura que es 2 veces m谩s peque帽a horizontal y verticalmente desde la pantalla. Esto se puede hacer casi siempre, ya que sabemos que los tama帽os de pantalla de los dispositivos son m煤ltiplos de 2, y si se hace, esto reducir谩 el tama帽o de la textura y facilitar谩 el desenfoque.

RenderTexture temp = RenderTexture.GetTemporary(_width, _height);
Graphics.Blit(_from_image.mainTexture, temp, _material);
RenderTexture.active = temp;

_texture.ReadPixels(new Rect(0, 0, temp.width, temp.height), 0, 0, false);
_texture.Apply();

_to_image.sprite = Sprite.Create(_texture, new Rect(0, 0, _texture.width, _texture.height), new Vector2(0.5f, 0.5f));
RenderTexture.ReleaseTemporary(temp);

Para capturar una imagen con mainTexture usando un sombreador (en _material) se usa Graphics.Blit. A continuaci贸n, memorizamos el resultado en la textura preparada y lo colocamos en la imagen de destino.

Todo estar铆a bien; en la pr谩ctica, se enfrent贸 a un efecto tal que, dependiendo del dispositivo, la imagen de fondo se voltea. La raz贸n despu茅s de un estudio del problema y la depuraci贸n se vuelve clara: la diferencia en los sistemas de coordenadasDirect3D y OpenGL, que Unity no puede ocultar. Al mismo tiempo, nuestro sombreador detecta los rayos UV y los procesa correctamente, y la inversi贸n ya ocurre en el entorno Unity (ReadPixels). Hay muchos consejos en la red, como "si te has puesto del rev茅s, dale la vuelta" o "cambia el signo UV". El uso de la macro UNITY_UV_STARTS_AT_TOP no ayud贸 a obtener una buena generalizaci贸n para todos los dispositivos bajo prueba. Adem谩s, por ejemplo, encontramos un caso tal que si prepara el ensamblaje para la emulaci贸n en Xcode en el iPhone, y Unity no us贸 Metal, sino solo OpenGLES, entonces debe interceptar casos como la emulaci贸n de un dispositivo que se ejecuta en otro software.

Despu茅s de probar varias opciones, me decid铆 por dos tabletas. El primero es forzar el renderizado de la c谩mara.(configuraci贸n forceIntoRenderTexture en el momento de la captura de imagen). El segundo es la determinaci贸n del tipo de sistema gr谩fico sobre la marcha a trav茅s de SystemInfo.graphicsDeviceType, que permite definir OpenGL-like o Direct3D-like (el primer grupo es OpenGLES2, OpenGLES3, OpenGLCore y Vulkan). Adem谩s, en nuestra aplicaci贸n para Direct3D similar, tenemos que entregar, que se realiza de procedimiento (por ejemplo, como este ).

Conclusi贸n


Espero que este art铆culo sea 煤til para que alguien supere un rastrillo desconocido, mejore la vida de los usuarios y comprenda Unity. Si nos fijamos en el efecto en uso en combate, a continuaci贸n, en la unidad se ve como este . En la aplicaci贸n, las sensaciones son algo diferentes, pero esta animaci贸n puede dar una idea suficiente.

All Articles