aboutsummaryrefslogtreecommitdiff
path: root/system/shaders/convolution-6x6_d3d.fx
blob: cb9510a9c53848f4420fe714947063b2fb9d9034 (plain)
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 *      Copyright (C) 2005-2010-2013 Team XBMC
 *      http://www.xbmc.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with XBMC; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

texture g_Texture;
texture g_KernelTexture;
float2  g_StepXY;

sampler RGBSampler =
  sampler_state {
    Texture = <g_Texture>;
    AddressU = CLAMP;
    AddressV = CLAMP;
    MinFilter = POINT;
    MagFilter = POINT;
  };

sampler KernelSampler =
  sampler_state
  {
    Texture = <g_KernelTexture>;
    AddressU = CLAMP;
    AddressV = CLAMP;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
  };

struct VS_OUTPUT
{
  float4 Position   : POSITION;
  float2 TextureUV  : TEXCOORD0;
};

struct PS_OUTPUT
{
  float4 RGBColor : COLOR0;
};

half3 weight(float pos)
{
  half3 w;
#ifdef HAS_RGBA
  w = tex1D(KernelSampler, pos).rgb;
#else
  w = tex1D(KernelSampler, pos).bgr;
#endif

#ifdef HAS_FLOAT_TEXTURE
  return w;
#else
  return w * 2.0 - 1.0;
#endif
}

half3 pixel(float xpos, float ypos)
{
  return tex2D(RGBSampler, float2(xpos, ypos)).rgb;
}

half3 getLine(float ypos, float3 xpos1, float3 xpos2, half3 linetaps1, half3 linetaps2)
{
  return
    pixel(xpos1.r, ypos) * linetaps1.r +
    pixel(xpos1.g, ypos) * linetaps2.r +
    pixel(xpos1.b, ypos) * linetaps1.g +
    pixel(xpos2.r, ypos) * linetaps2.g +
    pixel(xpos2.g, ypos) * linetaps1.b +
    pixel(xpos2.b, ypos) * linetaps2.b;
}

PS_OUTPUT CONVOLUTION6x6(VS_OUTPUT In)
{
  PS_OUTPUT OUT;

  float2 pos = In.TextureUV + g_StepXY * 0.5;
  float2 f = frac(pos / g_StepXY);

  half3 linetaps1   = weight((1.0 - f.x) / 2.0);
  half3 linetaps2   = weight((1.0 - f.x) / 2.0 + 0.5);
  half3 columntaps1 = weight((1.0 - f.y) / 2.0);
  half3 columntaps2 = weight((1.0 - f.y) / 2.0 + 0.5);

  // kernel generation code made sure taps add up to 1, no need to adjust here.

  float2 xystart = (-2.0 - f) * g_StepXY + In.TextureUV;
  float3 xpos1 = float3(
      xystart.x,
      xystart.x + g_StepXY.x,
      xystart.x + g_StepXY.x * 2.0);
  float3 xpos2 = half3(
      xystart.x + g_StepXY.x * 3.0,
      xystart.x + g_StepXY.x * 4.0,
      xystart.x + g_StepXY.x * 5.0);

  OUT.RGBColor.rgb = getLine(xystart.y                   , xpos1, xpos2, linetaps1, linetaps2) * columntaps1.r +
					 getLine(xystart.y + g_StepXY.y      , xpos1, xpos2, linetaps1, linetaps2) * columntaps2.r +
					 getLine(xystart.y + g_StepXY.y * 2.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.g +
					 getLine(xystart.y + g_StepXY.y * 3.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.g +
					 getLine(xystart.y + g_StepXY.y * 4.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.b +
					 getLine(xystart.y + g_StepXY.y * 5.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.b;

  OUT.RGBColor.a = 1.0;
  return OUT;
}

technique SCALER_T
{
  pass P0
  {
    PixelShader  = compile ps_3_0 CONVOLUTION6x6();
    ZEnable = False;
    FillMode = Solid;
    FogEnable = False;
  }
};