关于opengl:从HLSL移植的GLSL Shader无法正常工作

GLSL Shader Ported From HLSL Is Not Working

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   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;
   }

碎片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
texture al_tex;
   sampler2D s = sampler_state {
      texture = ;
   };

   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:

1
2
3
4
5
6
7
8
9
10
11
12
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;
}

碎片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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给了我一个模糊,透明的原始版本。

是什么原因造成的?


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

1
2
3
varying vec4 varying_color;
[...]
     gl_FragColor = varying_color;

因此您进行的所有纹理获取和计算都不会对最终着色器输出产生任何影响(并且可能会被编译器完全删除)。您可能想要输出sum或对其进行修改,例如gl_FragColor = varying_color * sum;或您想要实现的任何效果。

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