描述
我如何进行模糊
我的着色器文件
static const char* ULBlurShader_vertexShader =
"uniform mat4 fpsWorldViewProjectionMatrix;\n"
"attribute vec4 gInPosition;\n"
"attribute vec2 gInTex0;\n"
"varying vec2 varTex0;\n"
"void main() {\n"
" gl_Position = fpsWorldViewProjectionMatrix * gInPosition;\n"
" varTex0 = gInTex0.xy;\n"
"}\n";
static const char* ULBlurShaderHor_pixelShader =
"uniform sampler2D sampler0; \n"
"uniform vec4 fpsGaussBlur; \n"
"uniform vec4 fpsGaussWeights[65]; \n"
"varying vec2 varTex0;\n"
"vec4 gaussBlurHorizontal(const int anRadius,vec2 avBaseCoo, vec2 avSamplerRes)"
"{ \n"
" float fStartX = avBaseCoo.x - anRadius*avSamplerRes.x; \n"
" vec4 color = vec4(0, 0, 0, 0); \n"
" for (int x = 0; x < anRadius * 2; x++) \n"
" { \n"
" color += texture2D(sampler0, vec2(fStartX + x*avSamplerRes.x, avBaseCoo.y))*fpsGaussWeights[x / 4][x % 4]; \n"
" } \n"
" return color; \n"
"}\n"
"void main() {\n"
" gl_FragColor.rgba = gaussBlurHorizontal(int(fpsGaussBlur.y), varTex0, vec2(fpsGaussBlur.z, fpsGaussBlur.w)); \n"
"}\n";
static const char* ULBlurShaderVert_pixelShader =
"uniform sampler2D sampler0; \n"
"uniform vec4 fpsGaussBlur; \n"
"uniform vec4 fpsGaussWeights[65]; \n"
"varying vec2 varTex0;\n"
"vec4 gaussBlurVertical(const int anRadius,vec2 avBaseCoo, vec2 avSamplerRes)"
"{ \n"
" float fStartY = avBaseCoo.y - (anRadius*avSamplerRes.y); \n"
" vec4 color = vec4(0, 0, 0, 0); \n"
" for(int y=0; y<anRadius*2; y++) \n"
" { \n"
" color += texture2D(sampler0, vec2(avBaseCoo.x, fStartY+y*avSamplerRes.y))*fpsGaussWeights[y/4][y%4]; \n"
" } \n"
" return color; \n"
"}\n"
"void main() {\n"
" gl_FragColor.rgba = gaussBlurVertical(int(fpsGaussBlur.y), varTex0, vec2(fpsGaussBlur.z, fpsGaussBlur.w));\n"
"}\n";
答案 0 :(得分:1)
我遇到了同样的问题,尤其是在模糊由alpha = 0.0的像素包围的文本时。文字会消失,直至无法看到(中间图像)。 然而,一旦我在模糊之后添加了“Gamma校正”步骤,我设法得到了更好的结果。
因此,对于您的情况,在模糊完成后,根据以下内容调整RGBA值:
color = pow(color, vec4(1.0/fGamma))
fGamma
位于float
和0.0
之间1.0
的位置(我在我的示例中使用了fGamma=5.0
)。
以下是一个非常好的解释链接: https://learnopengl.com/#!Advanced-Lighting/Gamma-Correction
答案 1 :(得分:0)
是的,不幸的是,透明度存在整体问题,当像素透明时,其他颜色通道会发生什么。如果您尝试绘制没有Alpha透明度的图像(使用RGB1),您将看到透明像素为黑色。对于至少某些情况,这似乎是自然的,但对所有情况都不是。想象一下,你有一个图像具有漂亮的纯白色渐变,从完全不透明度下降到包括完全透明。然后第一个像素将是(1,1,1,1),某个像素将是(1,1,1,0.5)并且接近结束它可能(1,1,1,0.00X)但是然后是下一个像素alpha为0的像素将变为(0,0,0,0)而不是(1,1,1,0)。所以这是你混合的黑色,你会看到黑色边框。
因此看起来png导出器可能会出错,因为所有透明像素仍应为红色但情况并非如此。如果图像具有不同的颜色(在您的情况下不仅仅是白色或红色),那么导出器可能无法预测这些像素的颜色。所以最后这是一个正确的状态。
因此,在这种情况下,您需要重新平衡透明像素的颜色混合。它还意味着更改模糊着色器的工作方式。在计算颜色时(但不是alpha),您需要忽略透明像素,或者根据透明度,Alpha通道,您需要根据颜色缩放效果。
我会在一个类似于模糊的特定权重中求和5个像素时给你一个例子。让我们说相对比例是1,2,5,2,1。你现在正在做的是color = (c1*1 + c2*2 + c3*5 + c4*2 + c5*1)/(1+2+5+2+1)
但你在这个等式中有一个优化,你已经有一个标准值,你调用fpsGaussWeights
在我的例子中是1/11, 2/11, 5/11
...(通过汇总(1+2+5+2+1)
收到了11个)所以你以c1*1/11 + c2*2/11
结束...现在让我们改变方程以包括alpha值。现在原来是
color = (c1*1*c1.a + c2*2*c2.a + c3*5*c3.a + c4*2*c4.a + c5*1*c5.a)/(1*c1.a+2*c2.a+5*c3.a+2*c4.a+1*c5.a)
但是你只需要在颜色部分这样做
color.rgb = (c1.rgb*1*c1.a + c2.rgb*2*c2.a + c3.rgb*5*c3.a + c4.rgb*2*c4.a + c5.rgb*1*c5.a)/(1*c1.a+2*c2.a+5*c3.a+2*c4.a+1*c5.a)
而alpha通道保留先前的模糊方程。因此,您可以看到您可能不再包含权重的标准化值,因为当乘以Alpha通道时,权重值的总和不会是1.0。
现在我希望您可以自己在for
循环中优化此等式。如果使用低精度,还要注意溢出。
看看这个作为参考(甚至可能只是工作,但我没有测试它甚至仔细检查它):
int sampleCount = 5;
float weights[sampleCount];
vec4 color = vec4(.0);
float fullWeight = .0;
for(int i=0; i<sampleCount; i++) {
float actualWeight = weights[i] * textureColor.a;
vec4 textureColor = ; // fetch the pixel
color.rgb += textureColor.rgb * actualWeight; // can produce overflow
/*
We may do the computation on the fly so we do not need to divide in the end. This will remove the overflow issue
color.rgb = (color.rgb*fullWeight + textureColor.rgb*actualWeight)/(fullWeight + actualWeight);
Leads to:
float newWeightResult = (fullWeight + actualWeight);
float leftWeight = fullWeight/(fullWeight + actualWeight); //will be less or equal then 1
float rightWeight = actualWeight/(fullWeight + actualWeight); //will be less or equal then 1
color.rgb = color.rgb*leftWeight + textureColor.rgb*rightWeight; // no overflow
The color.rgb /= fullWeight line needs to be removed when using this
*/
color.a += textureColor.a * weights[i];
fullWeight += actualWeight;
}
color.rgb /= fullWeight;
您使用的重量仍可按原样保留。我只使用(1,2,5 ......)所以更容易解释。