0

我有这个用于模糊的 HLSL 着色器:

   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;
   }

碎片

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 给了我一个不模糊、稍微透明的原始版本。

什么可能导致这种情况?

4

1 回答 1

1

在您的片段着色器中,您有:

varying vec4 varying_color;
[...]
     gl_FragColor = varying_color;

因此,您所做的所有纹理获取和计算对最终着色器输出没有任何影响(并且可能会被编译器完全删除)。您可能想要输出sum或修​​改它,例如使用gl_FragColor = varying_color * sum;或任何您想要达到的效果。

另一件事:在碎片着色器中,您定义了纹理大小的变化,但您没有从顶点着色器传递它们。这些应该是制服(或者,在现代 GLSL 中,还有一个textureSize()GLSL 函数,它允许您直接访问这些值而无需显式传递它们)。

于 2013-09-01T02:28:53.357 回答