Hola a todos, en junio OTUS lanzará nuevamente el curso Unity Games Developer . En previsión del comienzo del curso, hemos preparado una traducción de material interesante sobre el tema.
Hoy hablaremos sobre cómo combinar una malla de terreno (u otra malla) en Unity. Esta guía es bastante avanzada, pero intenté dividirla en pasos separados. Se supone que tiene habilidades generales de Unity y conocimientos básicos de C #. La guía está diseñada para amplificar, pero creo que también se puede aplicar al Shader Graph. Esta es mi primera guía, así que espero que sea lo suficientemente clara. Si quieres agregar algo, avísame. He incluido un kit de inicio aquí, que tiene algunos sombreadores adicionales para este proyecto, así como un kit básico para comenzar. Todos los archivos del proyecto del manual de hoy están disponibles para mis clientes por $ 5, pero en un futuro cercano, estarán disponibles para todos.→ Kit de inicio→ Todo el proyecto: , , . . , , , . ( ) unity . , , .
Vamos a empezar. Para comenzar, señalaré el problema y profundizaré en la teoría en la que se basará la solución. Para hacer una mezcla entre el terreno y otras mallas, debe decirle al sombreador de alguna manera dónde se produce la intersección con el terreno. Decir es más fácil que hacerlo, pero hay una manera. ¿Y en qué consiste? ¡Render Texture nos ayudará !¿Qué es una textura de renderizado?
Render Texture es, de hecho, la posición de la cámara, que se guarda en el archivo de activos. Render Texture en los juegos se usa con mayor frecuencia para cosas como crear pantallas de video vigilancia. Podemos usar la textura de renderizado para guardar la vista de la cámara en el editor para que esta textura pueda usarse como sombreador. Esto es útil porque podemos hornear información sobre nuestro terreno, como la altura, las normales y los colores, en una textura que luego se puede utilizar en tiempo de ejecución para combinar mallas y terran.El renderizado de texturas se usa para mostrar imágenes de ganso en televisores en Untitled Goose GamePersonalización
Para comenzar, creemos una nueva escena y terreno. Establezca un tamaño conveniente para el trabajo, por ejemplo, 200x200. Ahora puedes organizar el terreno como quieras. Luego cree una nueva capa y asígnele el nombre "Terreno" y asigne un terreno a esta capa. Esto es necesario para que la máscara de la cámara pueda grabar el terreno en la Textura de renderizado .Mi obra maestra terraneLos archivos fuente del proyecto tienen un prefabricado llamado "BlendBakingCamera" : arrástrelo al escenario. Obtendrá una cámara ortográfica simple. En la cámara, debe colocar una máscara de eliminación en una nueva capa de terreno. Coloque la cámara en el centro del terreno ligeramente por encima del punto más alto del terreno. Luego ajuste el plano de recorte lejano para que la cámara vea el suelo del terreno. Al final, la escena debería verse así:Shader de repuesto
Ahora que la cámara está configurada, debe encontrar una manera de registrar datos de terreno. Para esto necesitamos sombreadores de repuesto. The Replacement Shader parece una perspectiva dudosa; yo mismo no he entendido cómo funciona durante mucho tiempo. Pero, de hecho, todo es muy simple y efectivo. Usar el Sombreador de reemplazo significa esencialmente representar cada objeto en el campo de visión de la cámara con un solo sombreador, independientemente del sombreador que se superponga a los objetos. Como resultado, todos los objetos se renderizarán utilizando el sombreador de reemplazo seleccionado , que en realidad es solo un sombreador normal.El sombreador que necesitamos para mezclar es el sombreador de profundidad. Representa la profundidad de la escena y es un componente clave en la creación de nuestro efecto de fusión, ya que escribe los valores de profundidad de nuestra cámara en la textura para que podamos leerlos más tarde. Para obtener más información sobre este shader y el Shader de reemplazo en general, le recomiendo que lea este manual de Making Stuff Look Good in Unity .Ejemplo de sombreador de profundidadEmpecemos a hornear
Creemos
una nueva clase y llamémosla "TerrainBlendingBaker" . Comencemos implementando una máscara de profundidad para el terreno base. Más tarde volveremos a este script para agregar colores y normales.Definir varias variables.
public Shader depthShader;
public RenderTexture depthTexture;
private Camera cam;
Ahora creemos un nuevo método y llamémoslo "UpdateBakingCamera" . En este método, determinaremos los datos de la cámara que el sombreador puede necesitar para mezclar en variables globales.private void UpdateBakingCamera()
{
if (cam == null)
{
cam = GetComponent<Camera>();
}
Shader.SetGlobalFloat("TB_SCALE", GetComponent<Camera>().orthographicSize * 2);
Shader.SetGlobalFloat("TB_OFFSET_X", cam.transform.position.x - cam.orthographicSize);
Shader.SetGlobalFloat("TB_OFFSET_Z", cam.transform.position.z - cam.orthographicSize);
Shader.SetGlobalFloat("TB_OFFSET_Y", cam.transform.position.y - cam.farClipPlane);
Shader.SetGlobalFloat("TB_FARCLIP", cam.farClipPlane);
}
Ahora horneemos la profundidad del terreno en la textura.
[ContextMenu("Bake Depth Texture")]
public void BakeTerrainDepth()
{
UpdateBakingCamera();
if (depthShader != null && depthTexture != null)
{
cam.SetReplacementShader(depthShader, "RenderType");
cam.targetTexture = depthTexture;
Shader.SetGlobalTexture("TB_DEPTH", depthTexture);
}
else
{
Debug.Log("You need to assign the depth shader and depth texture in the inspector");
}
}
Los valores serán más claros cuando comencemos a trabajar con el sombreador. Aquí hay una pequeña imagen que puede arrojar algo de luz:Vamos a transferir el terreno a la textura de profundidad para leerlo más tarde y comprender dónde hacer la fusión.Ahora tenemos todo lo que necesitamos para crear el efecto de fusión básico en el sombreador. En este punto, el script se ve más o menos así: pastebin.com/xNusLJfhBien, ahora que tenemos el script, podemos agregarlo a la cámara de horneado que agregamos anteriormente. Los activos iniciales tienen un sombreador llamado 'DepthShader' (Inresin / Shaders / DepthShader) y una Textura de renderizado llamada 'Depth FieldRT' (Inresin / RenderTextures / DepthTextureRT) , debe colocarlos en los campos apropiados en el inspector.Después de eso, simplemente ejecute el método a través del menú contextual para hornear la profundidad del terreno en la Textura de renderizado .Shader
Finalmente creemos un sombreador para mezclar. Cree un nuevo sombreador de amplificación estándar y ábralo, asígnele el nombre 'TerrainBlending' más o menos.Ahora necesitamos crear un UV para la textura de renderizado . Esta será la diferencia entre el punto que se renderiza y la posición de la cámara de cocción escalada en relación con el área total. Las tres variables globales aquí son las que acabamos de declarar en el código. También establecemos worldY como una variable local, la necesitaremos más adelante.
Tomemos la textura de profundidad que asignamos como variable global (para esto, agregue un nodo de muestra de textura , hágalo global y asígnele el nombre 'TB_DEPTH'), si ponemos la salida en el sombreador de amplificación de depuración 'un campo , podemos ver qué sucede. Cree un plano con el material al que se aplicará nuestro nuevo sombreador.Entonces, en el sombreador, tenemos información sobre la profundidad, ahora necesitamos agregar un desplazamiento en y para obtener la fusión.
Este bloque escala la posición y de la máscara del plano de recorte lejano , resta este valor de la posición mundial a lo largo del eje y del punto que se está representando, y finalmente lo desplaza hacia el lado inferior del cuadro delimitador de la cámara (posición y de la cámara menos el plano del clip lejano ).Ya algo! Vemos cómo los bordes del avión se fusionan con el terreno.
Ok, hagamos que la mezcla sea más controlada.
Ahora podemos controlar el grosor y el área del terreno de mezcla.
Creo que incluso podemos agregar un poco de ruido. Usemos la posición mundial para generar ruido a partir de la textura.
Las texturas de ruido están en la carpeta de texturas en el proyecto de inicio, se pueden asignar en el inspector o como una constante en el sombreador.¡Finalmente es hora de agregar algunas texturas! Para comenzar, usemos algunas texturas simples de un solo color, agregué dos texturas a la carpeta con activos de textura. Convierta la textura 'SingleColorGrass' en una textura de terreno. Luego, en el sombreador, debe crear una textura de terreno y un nodo de textura de objeto . Cambiaremos entre ellos en el canal rojo de la máscara que acabamos de crear.
Y aquí está el sombreador completo:
agregar iluminación personalizada de toon o modelos de iluminación apagada proporcionará los mejores resultados para este sombreador. Encendí apagadosombreador de terreno y versión apagada del sombreador en el paquete completo disponible para patrocinadores.Terrane y mallas apagadasTambién recomiendo agregar un sombreador triplanar al terreno y posiblemente otras mallas. Puedo considerar este problema en la próxima guía.Bueno, casi hemos terminado con el tema principal de la guía de hoy. He agregado algunas secciones que pueden ayudar con la extensión del sombreador.Extensión del sombreador: normal
Agregué un sombreador regular a los archivos, puede usarlo para escribir normales en la superficie del terreno y también usar mezclas. Para mi juego, no necesito una mezcla normal, así que solo experimenté un poco, y parece que el experimento fue un éxito, y mi idea funciona bien para el terreno sin un alto grado de cambio de altura. Incluí el sombreador de mapeo normal en el directorio con los sombreadores de inicio. Aquí puede ver mi implementación básica del mapa normal:
el código es casi el mismo que con el mapa de profundidad, pero esta vez usaremos el mapa normal como sombreador de reemplazo . También agregué un conjunto de texturas de renderizado para grabar normal (aquí es posible que necesite una configuración adicional).Para que las normales funcionen bien, puede tomar un poco más de esfuerzo relacionado con el ajuste, y también puede haber una restricción asociada con los terrenos de bajo nivel (pero no he realizado suficientes pruebas para confirmar esto).Extensión del sombreador: todos los colores
No voy a profundizar en los detalles de este tema, ya que va más allá de lo que se requiere para mi juego, pero lo pensé mientras escribía esta guía. Para agregar mezclas de muchos colores, podemos seleccionar colores de terreno no iluminados y guardarlos como texturas. En este caso, estamos limitados por una resolución bastante baja, pero este método funciona bien cuando se usan texturas de terreno de un solo color y texturas de baja resolución, o cuando se usa un sangrado débil . Con ajustes menores, también se pueden aplicar a mallas de terreno.Aquí está el código para la opción multicolor:[Header("The following settings are only if using the multi-color terrain shader")]
public Shader unlitTerrainShader;
public RenderTexture surfaceTexture;
public Material unlitTerrainMaterial;
public Terrain yourTerrain;
[ContextMenu("Bake Surface Texture")]
public void BakeTerrainSurface()
{
UpdateBakingCamera();
if (yourTerrain == null)
{
Debug.Log("You need to assign a terrain to capture surface texture");
return;
}
StartCoroutine(BakeColors());
}
IEnumerator BakeColors()
{
Material tempTerrainMaterial = yourTerrain.materialTemplate;
yourTerrain.materialTemplate = unlitTerrainMaterial;
yield return 0;
cam.SetReplacementShader(unlitTerrainShader, "RenderType");
cam.targetTexture = surfaceTexture;
Shader.SetGlobalTexture("TB_SURFACE", surfaceTexture);
yield return 0;
cam.targetTexture = null;
yourTerrain.materialTemplate = tempTerrainMaterial;
yield return null;
}
El único cambio en el sombreador es que, en lugar de usar una textura predefinida, usamos una textura de superficie del terreno definida globalmente que usará la posición relativa como UV. Una extensión adicional le permite obtener una combinación más agradable de texturas.
Mezcla de texturas múltiples
Aquí hay un gráfico multicolor completo con un sombreador de mezcla normal:
Conclusión
¡Felicitaciones si has leído hasta este punto! Como dije, esta es mi primera guía, por lo que agradecería mucho sus comentarios. Si quieres apoyarme en la creación de juegos y tutoriales, échale un vistazo aquí o suscríbete a mi Twitter .
Aprende más sobre el curso