2
// Copyright 1997 - 2001, Paul C. Gregory
4
// Contact: pgregory@aqsis.org
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
\brief Implement the filters of the RenderMan API functions.
23
\author Paul C. Gregory (pgregory@aqsis.org)
34
START_NAMESPACE( Aqsis )
36
// Mitchell Filter Declarations
37
class MitchellFilter {
39
// MitchellFilter Public Methods
40
MitchellFilter(TqFloat b, TqFloat c, TqFloat xw, TqFloat yw)
47
TqFloat Evaluate(TqFloat x, TqFloat y) const {
48
return Evaluate(x * invXWidth) * Evaluate(y * invYWidth);
50
TqFloat Evaluate(TqFloat x) const {
53
return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x +
54
(-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f);
56
return ((12 - 9*B - 6*C) * x*x*x +
57
(-18 + 12*B + 6*C) * x*x +
58
(6 - 2*B)) * (1.f/6.f);
62
TqFloat invXWidth, invYWidth;
65
END_NAMESPACE( Aqsis )
67
//----------------------------------------------------------------------
69
// Gaussian filter used as a possible value passed to RiPixelFilter.
72
RtFloat RiGaussianFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
75
* d = distance from origin
76
* w = filterwidth ([COOK84a] article used 1.5)
77
* For here use sqrt( (xwidth/2)*(xwidth/2) + (ywidth/2)*(ywidth/2) ).
80
* w = sqrt( (xwidth*xwidth)/2 + (ywidth*ywidth)/2 )
81
* w = sqrt( (xwidth*xwidth + ywidth*ywidth)/2 )
82
* w*w = (xwidth*xwidth + ywidth*ywidth)/2
84
* if (d < filterwidth) then 0
85
* else exp(-d*d) - exp(-w*w)
90
///* d = sqrt(x*x+y*y), d*d = (x*x+y*y) */
94
//w2 = 0.5*(xwidth*xwidth + ywidth*ywidth);
100
// return(exp(-d2) - exp(-w2));
102
// The above version falls faster than the one used by the 3.2 spec
103
// PRMan and RenderDotC. Since all three match exactly, might as
104
// well change to the code below:
108
return exp( -2.0 * ( x * x + y * y ) );
112
//----------------------------------------------------------------------
114
// Mitchell filter used as a possible value passed to RiPixelFIlter.
117
RtFloat RiMitchellFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
119
Aqsis::MitchellFilter mc(1/3.0f, 1/3.0f, xwidth, ywidth);
121
return mc.Evaluate(x, y);
124
//----------------------------------------------------------------------
126
// Box filter used as a possible value passed to RiPixelFIlter.
129
RtFloat RiBoxFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
131
/* [UPST89] -- (RC p. 178) says that x and y will be in the
132
* following intervals:
133
* -xwidth/2 <= x <= xwidth/2
134
* -ywidth/2 <= y <= ywidth/2
135
* These constraints on x and y really simplifies the
136
* the following code to just return (1.0).
139
return MIN( ( fabs( x ) <= xwidth / 2.0 ? 1.0 : 0.0 ),
140
( fabs( y ) <= ywidth / 2.0 ? 1.0 : 0.0 ) );
144
//----------------------------------------------------------------------
146
// Triangle filter used as a possible value passed to RiPixelFilter
149
RtFloat RiTriangleFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
151
RtFloat hxw = xwidth / 2.0;
152
RtFloat hyw = ywidth / 2.0;
153
RtFloat absx = fabs( x );
154
RtFloat absy = fabs( y );
156
/* This function can be simplified as well by not worrying about
157
* returning zero if the sample is beyond the filter window.
159
return MIN( ( absx <= hxw ? ( hxw - absx ) / hxw : 0.0 ),
160
( absy <= hyw ? ( hyw - absy ) / hyw : 0.0 ) );
164
//----------------------------------------------------------------------
165
// RiCatmullRomFilter
166
// Catmull Rom filter used as a possible value passed to RiPixelFilter.
169
RtFloat RiCatmullRomFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
172
* From page 223 of [MITC88]
175
* f(d) = 1/6*( (12-9*B-9*C)*abs(d*d*d)
176
* + (-18 + 12*B + 6*C)*d*d + (6-2*B) )
179
* f(d) = 1/6*( (-B-6*C)*abs(d*d*d)
186
* -------------------------------------------------------------
187
* When B = 0.0 and C = 0.5 the filter is a Catmull-Rom cubic spline.
190
* f(d) = 1/6*[ (12-3)*abs(d*d*d) + (-18 + 3)*d*d + (6) ]
193
* f(d) = 1/6*[ (-3)*abs(d*d*d) + (15)*d*d + (-24)*d + (12) ]
196
* -------------------------------------------------------------
200
* f(d) = (3/2)*abs(d*d*d) - (5/2)*d*d + 1
203
* f(d) = (-0.5)*abs(d*d*d) + (5/2)*d*d - 4*abs(d) + 2
210
d2 = x * x + y * y; // d*d
211
d = sqrt( d2 ); // distance from origin
214
return ( 1.5 * d * d2 - 2.5 * d2 + 1.0 );
216
return ( -d * d2 * 0.5 + 2.5 * d2 - 4.0 * d + 2.0 );
221
RtFloat r2 = (x*x+y*y);
222
RtFloat r = sqrt(r2);
224
(r<1.0)?(3.0*r*r2-5.0*r2+2.0):(-r*r2+5.0*r2-8.0*r+4.0);
228
//----------------------------------------------------------------------
230
// Sinc filter used as a possible value passed to RiPixelFilter.
233
RtFloat RiSincFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
240
// return(sin(RI_PI*d)/(RI_PI*d));
244
// The above is an un-windowed sinc, below is a windowed sinc
245
// function similar in shape to what PRMan 3.9 uses.
248
/* Modified version of the RI Spec 3.2 sinc filter to be
249
* windowed with a positive lobe of a cosine which is half
250
* of a cosine period.
253
/* Uses a -PI to PI cosine window. */
257
x = cos( 0.5 * x / xwidth ) * sin( x ) / x;
266
y = cos( 0.5 * y / ywidth ) * sin( y ) / y;
273
/* This is a square separable filter and is the 2D Fourier
274
* transform of a rectangular box outlining a lowpass bandwidth
275
* filter in the frequency domain.
281
//----------------------------------------------------------------------
282
// RiDiskFilter -- this is in Pixar's ri.h
283
// Cylindrical filter used as a possible value passed to RiPixelFilter
286
RtFloat RiDiskFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
295
d = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
307
//----------------------------------------------------------------------
308
// RiBesselFilter -- this is in Pixar's ri.h
309
// Besselj0 filter used as a possible value passed to RiPixelFilter
312
RtFloat RiBesselFilter( RtFloat x, RtFloat y, RtFloat xwidth, RtFloat ywidth )
323
w = ( xx ) / ( xwidth * xwidth ) + ( yy ) / ( ywidth * ywidth );
329
/* Half cosine window. */
330
w = cos( 0.5 * RI_PI * sqrt( w ) );
331
return w * 2*j1( RI_PI * d ) / d;
344
//---------------------------------------------------------------------