mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-05 11:32:29 +02:00
376 lines
16 KiB
ObjectPascal
376 lines
16 KiB
ObjectPascal
//------------------------------------------------------------------------
|
|
//
|
|
// 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.
|