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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 | //------------------------------------------------------------------------
//
// Author : Dario Corno (rIo) / Jeff Molofee (NeHe)
// Converted to Delphi : Jan Horn
// Email : jhorn@global.co.za// Website : http://www.sulaco.co.za
// Authors Web Site : http://www.spinningkids.org/rio
// Date : 14 October 2001
// Version : 1.0
// Description : Radial Blur//
// Adapted to FPC : Sebastian Guenther (sg@freepascal.org) 2001-11-21
//
//------------------------------------------------------------------------
program RadialBlur;
{$mode objfpc}
uses GL, GLU, GLUT;
const
WND_TITLE = 'Radial Blur';
type TVector = Array[0..2] of glFloat;
var ElapsedTime : Integer; // Elapsed time between frames
// Textures
BlurTexture : glUint; // An Unsigned Int To Store The Texture Number
// User vaiables
Angle : glFloat;
Vertexes : Array[0..3] of TVector;
normal : TVector;
const
FPSCount : Integer = 0; // Counter for FPS
// Lights and Materials
globalAmbient : Array[0..3] of glFloat = (0.2, 0.2, 0.2, 1.0); // Set Ambient Lighting To Fairly Dark Light (No Color)
Light0Pos : Array[0..3] of glFloat = (0.0, 5.0, 10.0, 1.0); // Set The Light Position Light0Ambient : Array[0..3] of glFloat = (0.2, 0.2, 0.2, 1.0); // More Ambient Light
Light0Diffuse : Array[0..3] of glFloat = (0.3, 0.3, 0.3, 1.0); // Set The Diffuse Light A Bit Brighter
Light0Specular : Array[0..3] of glFloat = (0.8, 0.8, 0.8, 1.0); // Fairly Bright Specular Lighting
LmodelAmbient : Array[0..3] of glFloat = (0.2, 0.2, 0.2, 1.0); // And More Ambient Light
function EmptyTexture : glUint;
var txtnumber : glUint;
pData : Pointer;begin
// Create Storage Space For Texture Data (128x128x4)
GetMem(pData, 128*128*4);
glGenTextures(1, @txtnumber); // Create 1 Texture glBindTexture(GL_TEXTURE_2D, txtnumber); // Bind The Texture
glTexImage2D(GL_TEXTURE_2D, 0, 4, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
result :=txtNumber;
end;
procedure ReduceToUnit(var vector : Array of glFloat);var length : glFLoat;
begin
// Calculates The Length Of The Vector
length := sqrt((vector[0]*vector[0]) + (vector[1]*vector[1]) + (vector[2]*vector[2]));
if Length = 0 then Length :=1;
vector[0] :=vector[0] / length;
vector[1] :=vector[1] / length;
vector[2] :=vector[2] / length;end;
procedure calcNormal(const v : Array of TVector; var cross : Array of glFloat);
var v1, v2 : Array[0..2] of glFloat;begin
// Finds The Vector Between 2 Points By Subtracting
// The x,y,z Coordinates From One Point To Another.
// Calculate The Vector From Point 1 To Point 0 v1[0] := v[0][0] - v[1][0]; // Vector 1.x=Vertex[0].x-Vertex[1].x
v1[1] := v[0][1] - v[1][1]; // Vector 1.y=Vertex[0].y-Vertex[1].y
v1[2] := v[0][2] - v[1][2]; // Vector 1.z=Vertex[0].y-Vertex[1].z
// Calculate The Vector From Point 2 To Point 1
v2[0] := v[1][0] - v[2][0]; // Vector 2.x=Vertex[0].x-Vertex[1].x v2[1] := v[1][1] - v[2][1]; // Vector 2.y=Vertex[0].y-Vertex[1].y
v2[2] := v[1][2] - v[2][2]; // Vector 2.z=Vertex[0].z-Vertex[1].z
// Compute The Cross Product To Give Us A Surface Normal
cross[0] := v1[1]*v2[2] - v1[2]*v2[1]; // Cross Product For Y - Z
cross[1] := v1[2]*v2[0] - v1[0]*v2[2]; // Cross Product For X - Z cross[2] := v1[0]*v2[1] - v1[1]*v2[0]; // Cross Product For X - Y
ReduceToUnit(cross); // Normalize The Vectors
end;
// Draws A Helix
procedure ProcessHelix;
const Twists = 5;
MaterialColor : Array[1..4] of glFloat = (0.4, 0.2, 0.8, 1.0); Specular : Array[1..4] of glFloat = (1, 1, 1, 1);
var x, y, z : glFLoat;
phi, theta : Integer;
r, u, v : glFLoat;
begin glLoadIdentity(); // Reset The Modelview Matrix
gluLookAt(0, 5, 50, 0, 0, 0, 0, 1, 0); // Eye Position (0,5,50) Center Of Scene (0,0,0), Up On Y Axis
glPushMatrix(); // Push The Modelview Matrix
glTranslatef(0,0,-50); // Translate 50 Units Into The Screen glRotatef(angle/2.0, 1, 0, 0); // Rotate By angle/2 On The X-Axis
glRotatef(angle/3.0, 0, 1, 0); // Rotate By angle/3 On The Y-Axis
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, @MaterialColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, @specular);
r :=1.5; // Radius
glBegin(GL_QUADS); // Begin Drawing Quads
phi :=0; while phi < 360 do
begin
theta :=0;
while theta < 360*twists do
begin v := phi / 180.0 * pi; // Calculate Angle Of First Point ( 0 )
u := theta / 180.0 * pi; // Calculate Angle Of First Point ( 0 )
x :=cos(u)*(2 + cos(v))*r; // Calculate x Position (1st Point)
y :=sin(u)*(2 + cos(v))*r; // Calculate y Position (1st Point) z :=(u-(2*pi) + sin(v))*r; // Calculate z Position (1st Point)
vertexes[0][0] :=x; // Set x Value Of First Vertex
vertexes[0][1] :=y; // Set y Value Of First Vertex
vertexes[0][2] :=z; // Set z Value Of First Vertex
v :=(phi/180.0 * pi); // Calculate Angle Of Second Point ( 0 )
u :=((theta+20)/180.0 * pi); // Calculate Angle Of Second Point ( 20 )
x :=cos(u)*(2 + cos(v))*r; // Calculate x Position (2nd Point) y :=sin(u)*(2 + cos(v))*r; // Calculate y Position (2nd Point)
z :=(u-(2*pi) + sin(v))*r; // Calculate z Position (2nd Point)
vertexes[1][0] :=x; // Set x Value Of Second Vertex
vertexes[1][1] :=y; // Set y Value Of Second Vertex vertexes[1][2] :=z; // Set z Value Of Second Vertex
v :=(phi+20)/180.0*pi; // Calculate Angle Of Third Point ( 20 )
u :=(theta+20)/180.0*pi; // Calculate Angle Of Third Point ( 20 )
x :=cos(u)*(2 + cos(v))*r; // Calculate x Position (3rd Point)
y :=sin(u)*(2 + cos(v))*r; // Calculate y Position (3rd Point)
z :=(u-(2*pi) + sin(v))*r; // Calculate z Position (3rd Point)
vertexes[2][0] :=x; // Set x Value Of Third Vertex vertexes[2][1] :=y; // Set y Value Of Third Vertex
vertexes[2][2] :=z; // Set z Value Of Third Vertex
v :=(phi+20)/180.0*pi; // Calculate Angle Of Fourth Point ( 20 )
u :=theta / 180.0*pi; // Calculate Angle Of Fourth Point ( 0 )
x :=cos(u)*(2 + cos(v))*r; // Calculate x Position (4th Point)
y :=sin(u)*(2 + cos(v))*r; // Calculate y Position (4th Point)
z :=(u-(2*pi) + sin(v))*r; // Calculate z Position (4th Point)
vertexes[3][0] :=x; // Set x Value Of Fourth Vertex
vertexes[3][1] :=y; // Set y Value Of Fourth Vertex
vertexes[3][2] :=z; // Set z Value Of Fourth Vertex
calcNormal(vertexes, normal); // Calculate The Quad Normal
glNormal3f(normal[0],normal[1],normal[2]); // Set The Normal
// Render The Quad
glVertex3f(vertexes[0][0],vertexes[0][1],vertexes[0][2]); glVertex3f(vertexes[1][0],vertexes[1][1],vertexes[1][2]);
glVertex3f(vertexes[2][0],vertexes[2][1],vertexes[2][2]);
glVertex3f(vertexes[3][0],vertexes[3][1],vertexes[3][2]);
theta := theta + 20;
end; phi :=phi + 20;
end;
glEnd(); // Done Rendering Quads
glPopMatrix(); // Pop The Matrix
end;
// Set Up An Ortho View
procedure ViewOrtho;
begin glMatrixMode(GL_PROJECTION); // Select Projection
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
glOrtho( 0, 640 , 480 , 0, -1, 1 ); // Select Ortho Mode (640x480)
glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
end;
// Set Up A Perspective View
procedure ViewPerspective;
begin
glMatrixMode( GL_PROJECTION ); // Select Projection
glPopMatrix(); // Pop The Matrix glMatrixMode( GL_MODELVIEW ); // Select Modelview
glPopMatrix(); // Pop The Matrix
end;
// Renders To A Texture
procedure RenderToTexture;
begin
glViewport(0, 0, 128, 128); // Set Our Viewport (Match Texture Size)
ProcessHelix(); // Render The Helix glBindTexture(GL_TEXTURE_2D,BlurTexture); // Bind To The Blur Texture
// Copy Our ViewPort To The Blur Texture (From 0,0 To 128,128... No Border)
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 128, 128, 0);
glClearColor(0.0, 0.0, 0.5, 0.5); // Set The Clear Color To Medium Blue glClear(GL_COLOR_BUFFER_BIT OR GL_DEPTH_BUFFER_BIT); // Clear The Screen And Depth Buffer
glViewport(0, 0, 640 ,480); // Set Viewport (0,0 to 640x480)
end;
// Draw The Blurred Image
procedure DrawBlur(const times : Integer; const inc : glFloat);
var spost, alpha, alphainc : glFloat;
I : Integer;
begin alpha := 0.2;
spost := 0.0;
glEnable(GL_TEXTURE_2D); // Enable 2D Texture Mapping
glDisable(GL_DEPTH_TEST); // Disable Depth Testing
glBlendFunc(GL_SRC_ALPHA,GL_ONE); // Set Blending Mode glEnable(GL_BLEND); // Enable Blending
glBindTexture(GL_TEXTURE_2D,BlurTexture); // Bind To The Blur Texture
ViewOrtho(); // Switch To An Ortho View
alphainc := alpha / times; // alphainc=0.2f / Times To Render Blur
glBegin(GL_QUADS); // Begin Drawing Quads
// Number Of Times To Render Blur
For I :=0 to times-1 do
begin glColor4f(1.0, 1.0, 1.0, alpha); // Set The Alpha Value (Starts At 0.2)
glTexCoord2f(0+spost,1-spost); // Texture Coordinate ( 0, 1 )
glVertex2f(0,0); // First Vertex ( 0, 0 )
glTexCoord2f(0+spost,0+spost); // Texture Coordinate ( 0, 0 ) glVertex2f(0,480); // Second Vertex ( 0, 480 )
glTexCoord2f(1-spost,0+spost); // Texture Coordinate ( 1, 0 )
glVertex2f(640,480); // Third Vertex ( 640, 480 )
glTexCoord2f(1-spost,1-spost); // Texture Coordinate ( 1, 1 )
glVertex2f(640,0); // Fourth Vertex ( 640, 0 )
spost := spost + inc; // Gradually Increase spost (Zooming Closer To Texture Center)
alpha := alpha - alphainc; // Gradually Decrease alpha (Gradually Fading Image Out) end;
glEnd(); // Done Drawing Quads
ViewPerspective(); // Switch To A Perspective View
glEnable(GL_DEPTH_TEST); // Enable Depth Testing
glDisable(GL_TEXTURE_2D); // Disable 2D Texture Mapping
glDisable(GL_BLEND); // Disable Blending
glBindTexture(GL_TEXTURE_2D,0); // Unbind The Blur Texture
end;
{------------------------------------------------------------------}
{ Function to draw the actual scene }
{------------------------------------------------------------------}
procedure glDraw;begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
RenderToTexture; // Render To A Texture
ProcessHelix; // Draw Our Helix DrawBlur(25, 0.02); // Draw The Blur Effect
angle :=ElapsedTime / 5.0; // Update angle Based On The Clock
end;
{------------------------------------------------------------------}
{ Initialise OpenGL }
{------------------------------------------------------------------}
procedure glInit;begin
glClearColor(0.0, 0.0, 0.0, 0.5); // Black Background
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glClearDepth(1.0); // Depth Buffer Setup
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Realy Nice perspective calculations
glEnable(GL_DEPTH_TEST); // Enable Depth Buffer
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LmodelAmbient); // Set The Ambient Light Model
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @GlobalAmbient); // Set The Global Ambient Light Model
glLightfv(GL_LIGHT0, GL_POSITION, @light0Pos); // Set The Lights Position glLightfv(GL_LIGHT0, GL_AMBIENT, @light0Ambient); // Set The Ambient Light
glLightfv(GL_LIGHT0, GL_DIFFUSE, @light0Diffuse); // Set The Diffuse Light
glLightfv(GL_LIGHT0, GL_SPECULAR, @light0Specular); // Set Up Specular Lighting
glEnable(GL_LIGHTING); // Enable Lighting
glEnable(GL_LIGHT0); // Enable Light0
BlurTexture := EmptyTexture(); // Create Our Empty Texture
glShadeModel(GL_SMOOTH); // Select Smooth Shading
glMateriali(GL_FRONT, GL_SHININESS, 128);
end;
{------------------------------------------------------------------}
{ Handle window resize }
{------------------------------------------------------------------}procedure glResizeWnd(Width, Height : Integer);
begin
if (Height = 0) then // prevent divide by zero exception
Height := 1;
glViewport(0, 0, Width, Height); // Set the viewport for the OpenGL window glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection
glLoadIdentity(); // Reset View
gluPerspective(45.0, Width/glFloat(Height), 2.0, 200.0); // Do the perspective calculations. Last value = max clipping depth
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix glLoadIdentity(); // Reset View
end;
var DemoStart, LastTime : LongWord;
procedure DisplayWindow; cdecl;
begin Inc(FPSCount); // Increment FPS Counter
LastTime :=ElapsedTime;
ElapsedTime := glutGet(GLUT_ELAPSED_TIME) - DemoStart; // Calculate Elapsed Time
ElapsedTime :=(LastTime + ElapsedTime) DIV 2; // Average it out for smoother movement glDraw;
glutSwapBuffers;
Inc(ElapsedTime, 10);
glutPostRedisplay;
end;
procedure OnReshape(width, height: Integer); cdecl;
begin
glResizeWnd(width, height);
end;
begin
glutInit(@argc, argv);
glutInitDisplayMode(GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH); glutCreateWindow(WND_TITLE);
glutDisplayFunc(@DisplayWindow);
glutReshapeFunc(@OnReshape);
glutInitWindowSize(640, 480);
glInit;
DemoStart := glutGet(GLUT_ELAPSED_TIME);
glutMainLoop;
end. |