Código fuente del pequeño proyecto de Unity
Atten fijo = 1.0;
#De lo contrario
float 3 light coord = mul(_ light Matrix 0, float4(i.worldPos, 1)). xyz
atención fija = tex2D(_ textura ligera 0, punto(lightCoord, lightCoord).rr). UNITY _ ATTEN _ canal;
#endif
_LightMatrix0: esta variable se describe en la tabla y la documentación oficial en la página P184 de este libro. Se define en una macro específica en el archivo AutoLight.cginc integrado y se puede utilizar para convertir puntos del espacio mundial al espacio local de la fuente de luz. Entonces, la primera oración del código anterior "mul (_ lightmatrix0, float 4 (i.worldpos, 1)). XYZ" es convertir las coordenadas del vértice en coordenadas en el espacio de la fuente de luz, que también se explica en el libro.
_LightTexture0: similar a _LightMatrix0, también se define bajo una macro específica en el archivo integrado AutoLight.cginc, seguido de la definición de _LightMatrix0. Es una textura de atenuación que contiene información de atenuación de la fuente de luz. Podemos procesar aún más las coordenadas obtenidas por el primer código para obtener las coordenadas de muestreo de la textura de atenuación. Dado que Unity no explica oficialmente el significado específico del rango numérico de _LightMatrix0, podemos inferir que el rango del módulo de coordenadas obtenido por _LightMatrix0 será [0, 1], es decir, el lugar que coincide con la fuente de luz es (0, 0, 0), el valor del módulo en el límite del rango de la fuente de luz es 1. En la oración punto (lightCoord, lightCoord). rr, primero obtenga el cuadrado de la distancia de la fuente de luz del producto escalar, que es un escalar. Actuamos. Realizar la operación rr en esta variable es equivalente a construir un vector bidimensional. El valor de cada componente de este vector bidimensional es un valor escalar, obteniendo así una coordenada de muestreo bidimensional. Esta operación es una operación de cambio común en los sombreadores y también se explica en el sitio web oficial de Cg. Luego, usamos estas coordenadas bidimensionales para muestrear la textura de atenuación de iluminación _LightTexture0 y obtener el valor de atenuación. _LightTexture0 se analizará en detalle más adelante.
Este código no está estandarizado: el libro dice que el código de esta sección no se puede usar directamente en el proyecto, solo se usa para ilustrar el principio, pero si desea usar este código para publicar el proyecto directamente, es necesario modificarlo, porque todavía no estaba estandarizado. El motivo es que hay un problema con las condiciones de juicio de palabras clave de este código y es posible que _LightTexture0 o _LightMatrix0 no estén definidos. Podemos reemplazar el código original con el siguiente código (el nuevo código también se envió a github):
#ifdef use _DIRECTIONAL_LIGHT
Fixed atten = 1.0;
#De lo contrario
#Si se ha definido (punto)
//Convierte las coordenadas del punto al espacio de coordenadas de la fuente de luz puntual. _LightMatrix0 se calcula mediante el código del motor y se pasa al sombreador, que contiene el cálculo del rango de luz puntual. Consulte el código fuente del motor Unity para obtener más detalles. Después de la transformación _LightMatrix0, el lightCoord en el centro de la fuente de luz puntual es (0, 0, 0) y el módulo lightCoord en el borde del rango de la fuente de luz puntual es 1.
coord de luz flotante 3 = mul(_ matriz de luz 0, float4(i.worldPos, 1)). xyz
// Utilice el punto cuadrado (lightCoord, lightCoord) desde el punto hasta el centro de la fuente de luz para formar una coordenada de muestreo bidimensional y muestree la textura de atenuación _LightTexture0. Más adelante se podrá ver cómo se ve la textura de _LightTexture0.
// UNITY_ATTEN_CHANNEL es el canal de textura donde se encuentra el valor de atenuación, que se puede ver en el archivo HLSLSupport.cginc incorporado. UNITY_ATTEN_CHANNEL es un canal R para PC y plataformas host comunes, y también es un canal para plataformas móviles.
atención fija = tex2D(_ textura ligera 0, punto(lightCoord, lightCoord).rr). UNITY _ ATTEN _ canal;
#elif definición (en vivo)
// Convierte las coordenadas del punto al espacio de coordenadas del foco. _LightMatrix0 se calcula mediante el código del motor y se pasa al sombreador, que incluye el cálculo del alcance y el ángulo del foco. Consulte el código fuente del motor Unity para obtener más detalles. Después de la transformación _LightMatrix0, el lightCoord en el centro de la fuente de luz del foco o fuera del rango del foco es (0, 0, 0), y el módulo lightCoord en el borde del rango de la fuente de luz puntual es 1.
float 4 light coord = mul(_ light Matrix 0, float4(i.worldPos, 1));
//A diferencia de las fuentes de luz puntuales, los focos tienen más ángulos, etc. requisitos, por lo que para obtener el valor de atenuación, además de muestrear la textura de atenuación, también debe determinar el rango, el ángulo de apertura y la dirección del foco.
//En este momento, la textura de atenuación se almacena en _LightTextureB0, que es equivalente a _LightTexture0 en la fuente de luz puntual.
// _LightTexture0 del foco ya no almacena la textura de atenuación según la distancia, sino que almacena la textura de atenuación según el rango del ángulo de apertura.
Atención fija = (coord. de luz. z > 0) * tex2D (_LightTexture0, lightCoord.xy/lightCoord.w + 0.5). w *tex2D(_LightTextureB0, punto(lightCoord, lightCoord).rr). UNITY_ATTEN_channel;
#else
Atencion fija = 1.0;
#endif
#endif
Lo anterior El juicio de las condiciones de las palabras clave es más preciso, lo que garantiza que el código que accede a la textura de atenuación solo se ejecute en el momento correcto. _LightTexture0 y _LightMatrix0 solo se pueden definir bajo ciertas condiciones, como cuando POINT, SPOT, POINT_COOKIE y DIRECTIONAL_COOKIE están activados, esto se puede encontrar en AutoLight.cginc, pero dado que no hay un juicio estricto en el código original, Unity compilará estrictamente Unity Shader genera el programa de sombreado correspondiente según diferentes palabras clave al publicar, y nuestros errores serán descubiertos en este momento.