opengl - ¿Por qué mi shader GLSL está generando un clivaje?
libgdx fragment-shader (2)
Este es el resultado de restar la primera imagen del segundo:
El fondo en el primero no es completamente negro, de ahí el amarilleo a la derecha, pero de lo contrario se puede ver claramente la región negra a la izquierda donde se conservaron los valores originales, el arco más oscuro donde se evaluaron los valores de ambas luces pero el derecho mayor, luego toda el área a la derecha que la luz original no tocó.
Por lo tanto, creo que estás obteniendo una mezcla máxima. Pero lo que quieres es una mezcla aditiva:
Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE);
... y deje la ecuación de mezcla en el valor predeterminado de GL_FUNC_ADD
.
Estoy trabajando en una técnica de iluminación diferida en 2D, usando un buffer de cuadros para acumular fuentes de luz usando la ecuación de mezcla GL_MAX.
Esto es lo que obtengo cuando renderizo una fuente de luz (la geometría es un quad sin una textura, solo estoy usando un sombreador de fragmentos para colorear) en mi memoria intermedia:
Que es exactamente lo que quiero: atenuación de la fuente de luz. Sin embargo, cuando dos fuentes de luz están cerca una de la otra, cuando se superponen, parecen producir un valor de RGB más bajo donde se encuentran, así:
¿Por qué hay una línea más oscura entre los dos? Estaba esperando que con la ecuación de mezcla GL_MAX
combinen suavemente entre sí, usando el valor máximo de los fragmentos en cada ubicación.
Aquí está la configuración para el FBO (usando LibGDX):
Gdx.gl.glClearColor(0.14f, 0.14f, 0.19f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glBlendEquation(GLMAX_BLEND_EQUATION);
Gdx.gl.glBlendFunc(GL20.GL_SRC_COLOR, GL20.GL_DST_COLOR);
Gdx.gl.glEnable(GL20.GL_BLEND);
No creo que la llamada a glBlendFunc sea realmente necesaria al usar esta ecuación. GLMAX_BLEND_EQUATION
está establecido en 0x8008
.
varying vec2 v_texCoords;
varying vec2 v_positionRelativeToLight;
uniform sampler2D u_texture;
uniform vec3 u_lightPosition;
uniform vec3 u_lightColor;
void main() {
float distanceToLight = length(v_positionRelativeToLight);
float falloffVarA = 0.1;
float falloffVarB = 1.0;
float attenuation = 1.0 / (1.0 + (falloffVarA*distanceToLight) + (falloffVarB*distanceToLight*distanceToLight));
float minDistanceOrAttenuation = min(attenuation, 1.0-distanceToLight);
float combined = minDistanceOrAttenuation * attenuation;
gl_FragColor = vec4(combined, combined, combined, 1.0);
}
Hay variables extra pasadas allí ya que este sombreador de fragmentos suele ser más complicado, pero lo he cortado para mostrar cómo se comporta la atenuación y la fusión.
Esto sucede entre cada fuente de luz que represento donde se encuentran, en lugar del color que estoy esperando, el encuentro de dos fuentes de luz, el punto equidistante entre los dos cuádriceps, es un color más oscuro que el que estoy esperando. ¿Alguna idea de por qué y cómo solucionarlo?
Su resultado es la apariencia esperada para la mezcla máxima (que es como el modo de combinación aligerar en Photoshop). La costura oscura parece fuera de lugar debido a la caída no lineal de cada luz, pero es matemáticamente correcta. Si le introduce una luz con un color brillante que no sea blanco, se verá mucho más objetable.
Puedes evitar esto si transformas tus luces en un buffer de cuadros con colores invertidos y mezclas multiplicativas, y luego renderizas el buffer del cuadro con colores invertidos. Luego las matemáticas funcionan para no tener las costuras, pero no se verán inusualmente brillantes como lo que produce la mezcla de aditivos.
Use un color blanco claro puro en el buffer de su cuadro y luego renderice las luces con la ecuación de mezcla GL_ADD estándar y la función de mezcla GL_ONE_MINUS_DST_COLOR. A continuación, renderice su textura FBO en la pantalla, invirtiendo los colores nuevamente.
Dos luces dibujadas usando tu método
Dos luces dibujadas aditivamente
Dos luces, dibujadas secuencialmente con GL_ONE_MINUS_DST_COLOR, GL_ZERO y GL_ADD