📄 openglapp.dpr
字号:
//------------------------------------------------------------------------
//
// Author : Jan Horn
// Email : jhorn@global.co.za
// Website : http://www.sulaco.co.za
// http://home.global.co.za/~jhorn
// Date : 15 April 2002
// Version : 1.0
// Description : Particle Lines. I saw a similar effect on a demo once
// and tried to reproduce the effect here.
//
//------------------------------------------------------------------------
program OpenGLApp;
uses
Windows,
Messages,
OpenGL,
BMP;
const
WND_TITLE = 'Particle Lines by Jan Horn';
FPS_TIMER = 1; // Timer to calculate FPS
FPS_INTERVAL = 500; // Calculate FPS every 1000 ms
GRID_WIDTH = 30;
GRID_HEIGHT = 9;
TAIL_LENGTH = 6;
MAX_PARTICLES = 500;
type TVertex = Record
X, Y, Z : glInt;
end;
TParticle = Record
NextVertex : Integer; // vertex its traveling to
DestValue : Integer; // speed*elapsedtime value when it gets there.
Visited : Array[1..TAIL_LENGTH] of Integer; // last 5 visited vertices
Speed : Single; // speed of the particle
Step : glFloat;
end;
var
h_Wnd : HWND; // Global window handle
h_DC : HDC; // Global device context
h_RC : HGLRC; // OpenGL rendering context
keys : Array[0..255] of Boolean; // Holds keystrokes
FPSCount : Integer = 0; // Counter for FPS
ElapsedTime : Integer; // Elapsed time between frames
// Textures
particleTex : glUint;
backgroundTex : glUint;
// User variables
Particles : Integer = 150;
Grid : Array[0..GRID_WIDTH*GRID_WIDTH*GRID_HEIGHT] of TVertex; // grid of 100x100x7
Particle : Array[1..MAX_PARTICLES] of TParticle;
ShowBackground : Boolean = TRUE;
{$R *.RES}
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external opengl32;
{------------------------------------------------------------------}
{ Function to convert int to string. }
{------------------------------------------------------------------}
function IntToStr(Num : Integer) : String; // using SysUtils increase file size by 100K
begin
Str(Num, result);
end;
//--- Check if the particle has reached its destination. If it has, select a new destination
procedure UpdateParticles;
var I, P : Integer;
begin
for P :=1 to PARTICLES do
with Particle[P] do
begin
if ElapsedTime >= DestValue then // Check if the particle has reached its destination
begin
for I :=TAIL_LENGTH downto 2 do // store current location in visited list and thift the other up
Visited[I] :=Visited[I-1];
Visited[1] :=NextVertex;
// select a new random direction
repeat
I :=Random(6);
case I of
0 : if Visited[1] MOD GRID_WIDTH > 0 then NextVertex := Visited[1] - 1; // left
1 : if Visited[1] MOD GRID_WIDTH < GRID_WIDTH-1 then NextVertex := Visited[1] + 1; // right
2 : if Visited[1] MOD (GRID_WIDTH*GRID_WIDTH) > GRID_WIDTH then NextVertex := Visited[1] - GRID_WIDTH; // back
3 : if Visited[1] MOD (GRID_WIDTH*GRID_WIDTH) < GRID_WIDTH*GRID_WIDTH-GRID_WIDTH then NextVertex := Visited[1] + GRID_WIDTH; // forward
4 : if Visited[1] DIV (GRID_WIDTH*GRID_WIDTH) > 0 then NextVertex := Visited[1] - GRID_WIDTH*GRID_WIDTH; // down
5 : if Visited[1] DIV (GRID_WIDTH*GRID_WIDTH) < GRID_HEIGHT-1 then NextVertex := Visited[1] + GRID_WIDTH*GRID_WIDTH; // up
end;
if NextVertex <> Visited[1] then // not equal current vertex
if NextVertex <> Visited[2] then // not equal previous vertex
I :=-1;
until I = -1;
// calculate when the next endpoint will be reached
DestValue :=Round(((ElapsedTime DIV (Round(10/Speed)))*10+10)/Speed);
end;
end;
end;
//--- Draws the tail of the particle. Color fades away. Fast particles are red
procedure drawParticleTail;
var I, P : Integer;
C : glFloat;
begin
for P :=1 to PARTICLES do
with Particle[P] do
begin
// Draw the path of the particle and fade the color
Step := 1-(DestValue - ElapsedTime)/10*Speed;
glBegin(GL_LINE_STRIP);
glColor3f(1, 1, 1);
glVertex3f((Grid[NextVertex].X-Grid[Visited[1]].X)*Step + Grid[Visited[1]].X,
(Grid[NextVertex].Y-Grid[Visited[1]].Y)*Step + Grid[Visited[1]].Y,
(Grid[NextVertex].Z-Grid[Visited[1]].Z)*Step + Grid[Visited[1]].Z);
for I :=1 to TAIL_LENGTH-1 do
begin
C :=(TAIL_LENGTH-I)/TAIL_LENGTH - Step/TAIL_LENGTH;
if Speed < 0.05 then
glColor3f(C, C, 0.5+C)
else
glColor3f(0.5+C, C, C); // faster particles are red
glVertex3iv(@Grid[Visited[I]]);
end;
glColor3f(0, 0, 0.1);
glVertex3f((Grid[Visited[TAIL_LENGTH-1]].X-Grid[Visited[TAIL_LENGTH]].X)*Step + Grid[Visited[TAIL_LENGTH]].X,
(Grid[Visited[TAIL_LENGTH-1]].Y-Grid[Visited[TAIL_LENGTH]].Y)*Step + Grid[Visited[TAIL_LENGTH]].Y,
(Grid[Visited[TAIL_LENGTH-1]].Z-Grid[Visited[TAIL_LENGTH]].Z)*Step + Grid[Visited[TAIL_LENGTH]].Z);
glEnd();
end;
end;
//--- Draws the head of the particle. Fast particles are red
procedure drawParticleHead();
var P : Integer;
X, Y, Z : glFloat;
begin
glBindTexture(GL_TEXTURE_2D, particleTex);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
for P :=1 to Particles do
with Particle[P] do
begin
X :=(Grid[NextVertex].X-Grid[Visited[1]].X)*Step + Grid[Visited[1]].X;
Y :=(Grid[NextVertex].Y-Grid[Visited[1]].Y)*Step + Grid[Visited[1]].Y;
Z :=(Grid[NextVertex].Z-Grid[Visited[1]].Z)*Step + Grid[Visited[1]].Z;
if Particle[P].Speed < 0.05 then
glColor3f(1, 1, 1)
else
glColor3f(1, 0.7, 0.7); // faster particles are red
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(X-0.5, Y-0.5, Z);
glTexCoord2f(1.0, 0.0); glVertex3f(X+0.5, Y-0.5, Z);
glTexCoord2f(1.0, 1.0); glVertex3f(X+0.5, Y+0.5, Z);
glTexCoord2f(0.0, 1.0); glVertex3f(X-0.5, Y+0.5, Z);
glEnd();
end;
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
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
if ShowBackground then
begin
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, backgroundTex);
glTranslatef(0.0,0.0,-2.8);
glRotate(ElapsedTime/500, 0, 0, 1);
glColor3f(1, 1, 1);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -0.9, 0);
glTexCoord2f(1.0, 0.0); glVertex3f(+1.0, -0.9, 0);
glTexCoord2f(1.0, 1.0); glVertex3f(+1.0, +0.9, 0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, +0.9, 0);
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix;
end;
glTranslatef(0.0,0.0,-31);
glRotatef(20, 1, 0, 0);
glRotatef(ElapsedTime/300, 0, 1, 0);
// Check if the particle has reached its destination. If so, select a new destination
updateParticles;
// Draw the particle tail
drawParticleTail;
// Draw the actual particles
drawParticleHead;
end;
{------------------------------------------------------------------}
{ Initialise OpenGL }
{------------------------------------------------------------------}
procedure glInit();
var I, J : Integer;
begin
glClearColor(0.1, 0.1, 0.4, 0.0); // Black Background
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glClearDepth(1.0); // Depth Buffer Setup
// glEnable(GL_DEPTH_TEST); // Enable Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glBlendFunc(GL_ONE, GL_ONE);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Realy Nice perspective calculations
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
LoadTexture('particle.bmp', particleTex); // Load the Texture
LoadTexture('background.bmp', backgroundTex); // Load the Texture
glBindTexture(GL_TEXTURE_2D, particleTex); // Bind the Texture to the object
Randomize;
// Initialise all particles
for I :=1 to MAX_PARTICLES do
begin
Particle[I].Visited[1] :=random(GRID_WIDTH*GRID_WIDTH*GRID_HEIGHT);
for J :=2 to TAIL_LENGTH do
Particle[I].Visited[J] :=Particle[I].Visited[1];
Particle[I].NextVertex :=Particle[I].Visited[1];
Particle[I].Speed :=0.01 + Round(Random(5))/100;
Particle[I].DestValue :=0;
end;
// initialise grid
for I :=0 to GRID_WIDTH * GRID_WIDTH * GRID_HEIGHT-1 do
begin
Grid[I].X := I MOD GRID_WIDTH - (GRID_WIDTH DIV 2);
Grid[I].Z := (I DIV GRID_WIDTH) MOD GRID_WIDTH - (GRID_WIDTH DIV 2);
Grid[I].Y := (I DIV (GRID_WIDTH*GRID_WIDTH)) MOD GRID_HEIGHT - (GRID_HEIGHT DIV 2);
end;
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/Height, 1.0, 100.0); // Do the perspective calculations. Last value = max clipping depth
glMatrixMode(GL_MODELVIEW); // Return to the modelview matrix
glLoadIdentity(); // Reset View
end;
{------------------------------------------------------------------}
{ Processes all the keystrokes }
{------------------------------------------------------------------}
procedure ProcessKeys;
begin
if Keys[VK_ADD] then
begin
Inc(Particles);
if Particles > MAX_PARTICLES then
Particles :=MAX_PARTICLES;
end;
if Keys[VK_SUBTRACT] then
begin
Dec(Particles);
if Particles = 0then
Particles :=1;
end;
if Keys[Ord('B')] then
begin
ShowBackground :=NOT(ShowBackground);
Keys[Ord('B')] :=FALSE;
end;
end;
{------------------------------------------------------------------}
{ Determines the application抯 response to the messages received }
{------------------------------------------------------------------}
function WndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case (Msg) of
WM_CREATE:
begin
// Insert stuff you want executed when the program starts
end;
WM_CLOSE:
begin
PostQuitMessage(0);
Result := 0
end;
WM_KEYDOWN: // Set the pressed key (wparam) to equal true so we can check if its pressed
begin
keys[wParam] := True;
Result := 0;
end;
WM_KEYUP: // Set the released key (wparam) to equal false so we can check if its pressed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -