es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Espacio extraño entre las luces

Hace un par de semanas comencé a aprender a programar shaders. Quería crear un shader básico para mi proyecto 2D. Pero al hacerlo, me enfrenté al problema que se muestra aquí.

Hay extraños espacios entre los puntos de luz. Los fragmentos obtienen un valor de luz más bajo cuando dos o más fuentes de luz se tocan entre sí. No se me ocurre una forma de solucionar este problema.

Aquí está mi código (parte de él):
“`
struct Light{
float4 position;
float size;
};

//appdata y v2f

StructuredBuffer<light> LightData;
fixed4 frag (v2f i) : SVTarget{
float distance = 0;
fixed4 color = tex2D(MainTex, i.uv);
for(int a = 0; a < LightArraySize;a++){
if(distance>0){
if(distance > distance(i.worldSpacePos, _LightData[a].position+0.5)/LightData[a].size){
distance = distance(i.worldSpacePos, _LightData[a].position+0.5)/LightData[a].size;
}
}else{
distance = distance(i.worldSpacePos, _LightData[a].position+0.5)/LightData[a].size;
}
}
return fixed4(color.x – _distance, color.y – _distance, color.z – _distance, color.w);
}
“`

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema que estás enfrentando se debe al hecho de que no estás teniendo en cuenta la superposición entre las luces. Cuando dos o más luces se superponen, el cálculo de distancia que estás utilizando en tu shader devolverá un valor más bajo, lo que hace que los fragmentos reciban un valor de luz más bajo también.

    Una solución a este problema es utilizar una técnica llamada mezcla de luces. Esta técnica implica calcular las contribuciones de cada luz por separado y luego sumarlas para obtener el valor de luz final. De esta manera, se tiene en cuenta la superposición entre las luces.

    Para implementar la mezcla de luces, puedes modificar tu código de shader de la siguiente manera:

    • Calcula la distancia entre el fragmento y cada luz por separado utilizando la fórmula de distancia.
    • Calcula el valor de luz para cada luz utilizando la ley inversa del cuadrado (lightValue = lightIntensity / (distance * distance)).
    • Suma los valores de luz de todas las luces para obtener el valor de luz final para el fragmento.

    Aquí tienes un ejemplo de código:

    struct Light{
        float4 position;
        float size;
        float intensity;
    };
    
    StructuredBuffer<light> _LightData;
    
    fixed4 frag (v2f i) : SV_Target{
        float lightValue = 0;
        float totalDistance = 0;
    
        for(int a = 0; a < _LightArraySize; a++){
            float distanceToLight = distance(i.worldSpacePos, _LightData[a].position + 0.5) / _LightData[a].size;
            float lightContribution = _LightData[a].intensity / (distanceToLight * distanceToLight);
            lightValue += lightContribution;
            totalDistance += distanceToLight;
        }
    
        fixed4 color = tex2D(_MainTex, i.uv);
        float finalLightValue = lightValue / (1 + totalDistance);
    
        return float4(color.xyz * finalLightValue, color.w);
    } 
    

    En este código, calculamos la contribución de cada luz por separado utilizando la ley inversa del cuadrado, y luego las sumamos para obtener el valor de luz total. También llevamos un registro de la distancia total desde el fragmento hasta todas las luces, y utilizamos esto para ajustar el valor de luz final.

    Ten en cuenta que esta es solo una posible solución al problema que estás enfrentando, y puede haber otras formas de abordarlo según tus requisitos específicos.

Comments are closed.