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
133
134
135
136
137
138
|
//--------------------------------------------------------------------------------------
//
// Implementation of different downsampling methods for supersampled AA
//
// Copyright (c) NVIDIA Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
float2 SSTexelSize;
float blendFactor = 1.0;
sampler2D SSsampler = sampler_state
{
minFilter = Linear;
magFilter = Linear;
};
sampler2D DepthSSsampler = sampler_state
{
minFilter = Linear;
magFilter = Linear;
};
struct v2fConnector {
float4 projCoord : POSITION;
float2 tex : TEXCOORD0;
};
///////////////////////////////////////////////////////////////////////
// Vertex programs
///////////////////////////////////////////////////////////////////////
void vpPassThrough(float4 P : POSITION, float4 tc : TEXCOORD0, out v2fConnector v2f)
{
v2f.tex = tc.xy;
v2f.projCoord = P;
}
struct PixelOut
{
float4 color : COLOR;
float depth : DEPTH;
};
///////////////////////////////////////////////////////////////////////
// Fragment programs
///////////////////////////////////////////////////////////////////////
//
// Simple down samling : just using the fact we are in between 4 texels.
// so the HW will do a bilinear filtering of these 4 samples
//
PixelOut DownSample1( float2 tc : TEXCOORD0 )
{
PixelOut pix;
pix.color = f4tex2D(SSsampler, tc);
pix.depth = f4tex2D(DepthSSsampler, tc).r;
return pix;
}
//
// add 4 fetches around the original filtered one
// each of the 4 additional fetches will also benefit from the HW bilinear filtering
// the offsets are chosen to benefit from various texels in a specific % amout
//
PixelOut DownSample2( float2 tc : TEXCOORD0 )
{
float4 tap0 = f4tex2D(SSsampler, tc);
float4 tap1 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 0.4, 0.9 ));
float4 tap2 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -0.4, -0.9 ));
float4 tap3 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -0.9, 0.4 ));
float4 tap4 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 0.9, -0.4 ));
float4 color = 0.2 * ( tap0 + tap1 + tap2 + tap3 + tap4 );
float tap0d = f4tex2D(DepthSSsampler, tc).r;
float tap1d = f4tex2D(DepthSSsampler, tc + SSTexelSize * float2( 0.4, 0.9 )).r;
float tap2d = f4tex2D(DepthSSsampler, tc + SSTexelSize * float2( -0.4, -0.9 )).r;
float tap3d = f4tex2D(DepthSSsampler, tc + SSTexelSize * float2( -0.9, 0.4 )).r;
float tap4d = f4tex2D(DepthSSsampler, tc + SSTexelSize * float2( 0.9, -0.4 )).r;
float depth = 0.2 * ( tap0d + tap1d + tap2d + tap3d + tap4d );
PixelOut pix;
pix.color = color;
pix.depth = depth;
return pix;
}
//
// same process are the previous one
// but we are using 2 kernels : one 'normal', one bigger (more blurry, then)
// we will lerp from one to the other depending on downsampled alpha from the bigger kernel
// this technique is good to blur 'high frequencies' marked by alpha =0,
// i.e thin primitives, like lines or sharp triangles
//
float4 DownSample3( float2 tc : TEXCOORD0 ) : COLOR
{
float4 color;
float4 tap0 = f4tex2D(SSsampler, tc);
float4 tap1 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 0.4, 0.9 ));
float4 tap2 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -0.4, -0.9 ));
float4 tap3 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -0.9, 0.4 ));
float4 tap4 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 0.9, -0.4 ));
color = 0.2 * ( tap0 + tap1 + tap2 + tap3 + tap4 );
float4 tap11 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 0.9, 1.9 ));
float4 tap21 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -0.9, -1.9 ));
float4 tap31 = f4tex2D(SSsampler, tc + SSTexelSize * float2( -1.9, 0.9 ));
float4 tap41 = f4tex2D(SSsampler, tc + SSTexelSize * float2( 1.9, -0.9 ));
float4 color2 = 0.2 * ( tap0 + tap11 + tap21 + tap31 + tap41 );
float mask = saturate(color2.w * 1);
color = lerp(color2, color, mask);
color.w = mask;
return color;
}
///////////////////////////////////////////////////////////////////////
// Technique
///////////////////////////////////////////////////////////////////////
technique DownSample_Filter1
{
pass drawFinal
{
DepthMask = true;
VertexProgram = compile arbvp1 vpPassThrough();
FragmentProgram = compile arbfp1 DownSample1();
}
}
technique DownSample_Filter2
{
pass drawFinal
{
DepthMask = true;
VertexProgram = compile arbvp1 vpPassThrough();
FragmentProgram = compile arbfp1 DownSample2();
}
}
technique DownSample_Filter3
{
pass drawFinal
{
DepthMask = true;
VertexProgram = compile arbvp1 vpPassThrough();
FragmentProgram = compile arbfp1 DownSample3();
}
}
|