为什么我的GLSL着色器呈现解理?

时间:2016-04-05 12:10:04

标签: opengl libgdx glsl fragment-shader

我正在研究2D中的延迟光照技术,使用帧缓冲来使用GL_MAX混合方程来累积光源。

这是我在渲染一个光源时得到的结果(几何图形是没有纹理的四边形,我只是使用片段着色器进行着色)到我的缓冲区:

enter image description here

这正是我想要的 - 来自光源的衰减。然而,当两个光源彼此靠近时,当它们重叠时,它们似乎会产生较低的RGB值,如下所示:

enter image description here

为什么两者之间有一条较暗的线?我期望用GL_MAX混合方程,它们可以平滑地相互融合,使用每个位置的片段的最大值

这里是FBO的设置(使用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);

我不认为在使用这个等式时实际上需要调用glBlendFunc。 GLMAX_BLEND_EQUATION设置为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);
}

由于此片段着色器通常更复杂,因此传递了额外的变量,但我已将其剪切为仅显示衰减和混合的行为。

这发生在我渲染的每个光源之间 - 而不是我期待的颜色,两个光源的会面 - 两个四边形之间的等距点,是一种颜色较深的I&# 39;我期待。知道为什么以及如何解决它?

2 个答案:

答案 0 :(得分:5)

这是从第二个图像中减去第一个图像的结果:

Result of image 1 subtracted from image 2

第一个背景不是很黑,因此右边是黄色,但是你可以清楚地看到左边的黑色区域保存了原始值,两个灯的值都是较暗的弧线。评估但权利更大,然后右边的所有区域原始光线都没有触及。

因此,我认为您正在获得最大选择混合。但你想要的是添加剂混合:

colon

...并将混合等式保留为默认值Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE);

答案 1 :(得分:3)

您的结果是最大混合的预期外观(就像Photoshop中的淡化混合模式一样)。暗缝看起来不合适可能是因为每个灯的非线性衰减,但它在数学上是正确的。如果你为它引入一种明亮的非白色的灯,它会显得更令人讨厌。

如果将灯光渲染到具有反转颜色和乘法混合的帧缓冲区,然后使用反转颜色渲染帧缓冲区,则可以解决此问题。然后数学计算出没有接缝,但它看起来不会像添加剂混合产生的那样异常明亮。

在帧缓冲区上使用纯白色的清晰颜色,然后使用标准GL_ADD混合方程和混合函数GL_ONE_MINUS_DST_COLOR渲染灯光。然后将FBO纹理渲染到屏幕上,再次反转颜色。

使用您的方法绘制两盏灯 enter image description here

添加两个灯光 enter image description here

使用GL_ONE_MINUS_DST_COLOR,GL_ZERO和GL_ADD 依次绘制两盏灯 enter image description here

以上结果,倒置 enter image description here