我有这个HLSL Shader用于模糊:
struct VS_INPUT
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float4 Color : TEXCOORD1;
};
struct VS_OUTPUT
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
float4x4 al_projview_matrix;
VS_OUTPUT vs_main(VS_INPUT Input)
{
VS_OUTPUT Output;
Output.Position = mul(Input.Position, al_projview_matrix);
Output.Color = Input.Color;
Output.TexCoord = Input.TexCoord;
return Output;
}
Frag
texture al_tex;
sampler2D s = sampler_state {
texture = <al_tex>;
};
int tWidth;
int tHeight;
float blurSize = 5.0;
float4 ps_main(VS_OUTPUT Input) : COLOR0
{
float2 pxSz = float2(1.0 / tWidth,1.0 / tHeight);
float4 outC = 0;
float outA = 0;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-4.0 * pxSz.y * blurSize)).a * 0.05;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-3.0 * pxSz.y * blurSize)).a * 0.09;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-2.0 * pxSz.y * blurSize)).a * 0.12;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,-pxSz.y * blurSize)).a * 0.15;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,0)).a * 0.16;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,pxSz.y * blurSize)).a * 0.15;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,2.0 * pxSz.y * blurSize)).a * 0.12;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,3.0 * pxSz.y * blurSize)).a * 0.09;
outA += Input.Color.a * tex2D(s, Input.TexCoord.xy + float2(0,4.0 * pxSz.y * blurSize)).a * 0.05;
outC.a = outA;
return outC;
}
横向有类似的......
我的想法是,我为纹理和高度提供tWidth,tHeight,并使用它来获得相对于UV坐标的像素的“大小”。
然后我通过对邻居进行加权平均来使用它来进行正常模糊。
我把它移植到GLSL:
attribute vec4 al_pos;
attribute vec4 al_color;
attribute vec2 al_texcoord;
uniform mat4 al_projview_matrix;
varying vec4 varying_color;
varying vec2 varying_texcoord;
void main()
{
varying_color = al_color;
varying_texcoord = al_texcoord;
gl_Position = al_projview_matrix * al_pos;
}
分片
uniform sampler2D al_tex;
varying float blurSize;
varying float tWidth;
varying float tHeight;
varying vec2 varying_texcoord;
varying vec4 varying_color;
void main()
{
vec4 sum = vec4(0.0);
vec2 pxSz = vec2(1.0 / tWidth,1.0 / tHeight);
// blur in x
// take nine samples, with the distance blurSize between them
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-4.0 * pxSz.y * blurSize))* 0.05;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-3.0 * pxSz.y * blurSize))* 0.09;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-2.0 * pxSz.y * blurSize))* 0.12;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,-pxSz.y * blurSize))* 0.15;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,0))* 0.16;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,pxSz.y * blurSize))* 0.15;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,2.0 * pxSz.y * blurSize))* 0.12;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,3.0 * pxSz.y * blurSize))* 0.09;
sum += texture2D(al_tex, varying_texcoord.xy + vec2(0,4.0 * pxSz.y * blurSize))* 0.05;
gl_FragColor = varying_color * sum;
}
这有点不同,但它的逻辑是一样的。我将像素坐标转换为UV坐标,并乘以模糊因子,与hlsl因子相同。然而,glsl给了我一个不模糊,略微透明的原版。
是什么导致这种情况?
答案 0 :(得分:1)
在片段着色器中,您有:
varying vec4 varying_color;
[...]
gl_FragColor = varying_color;
所以你所做的所有纹理提取和计算都不会对最终的着色器输出产生任何影响(并且可能会被编译器完全删除)。您可能希望输出sum
或修改它,例如使用gl_FragColor = varying_color * sum;
或您想要达到的效果。
另一件事:在frag着色器中,您可以为纹理大小定义变化,但不要从顶点着色器传递它们。那些应该是制服(或者,在现代GLSL中,还有textureSize()
GLSL函数,它允许你直接删除那些值,而不会明确地传递它们。)