====== Примеры с библиотекой GLUT ====== **Автор:** //Romtek// (Romiras) Здесь размещены некоторые примеры, спортированные из примеров GLUT от SGI (язык С), а также от //Jan Horn// (язык Delphi c WinAPI). Большинство примеров должно работать в Windows/Linux без изменений кода, необходимо только наличие драйверов (библиотек) OpenGL, GLU, GLUT/libgl, libglu,libglut. ==== Scene demo ==== {{ articles:scene.png }} (*** << Scene demo >> Ported to Free Pascal by Romiras, Feb 2005 ***) {$apptype GUI} {$mode objfpc} Uses GL, GLU, GLUT; var oglWin : integer; procedure myinit(); const light_ambient: array [0..3] of GLfloat = (0.0,0.0,0.0,1.0); light_diffuse: array [0..3] of GLfloat = (1.0,0.0,0.0,1.0); light_specular: array [0..3] of GLfloat = (1.0,1.0,1.0,1.0); (* light_position is NOT default value *) light_position: array [0..3] of GLfloat = (1.0,1.0,1.0,0.0); begin glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular); glLightfv(GL_LIGHT0,GL_POSITION,light_position); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); end; procedure display(); cdecl; begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glPushMatrix(); glScalef(1.3,1.3,1.3); glRotatef(20.0,1.0,0.0,0.0); glPushMatrix(); glTranslatef(-0.75,0.5,0.0); glRotatef(90.0,1.0,0.0,0.0); glutSolidTorus(0.275,0.85,10,15); glPopMatrix(); glPushMatrix(); glTranslatef(-0.75,-0.5,0.0); glRotatef(270.0,1.0,0.0,0.0); glutSolidTetrahedron(); glPopMatrix(); glPushMatrix(); glTranslatef(0.75,0.0,-1.0); glutSolidIcosahedron(); glPopMatrix(); glPopMatrix(); glFlush(); end; procedure myReshape(w,h: longint); cdecl; var aspect: glFloat; begin glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); aspect := w/h; if w<=h then glOrtho(-2.5,2.5, -2.5/aspect, 2.5/aspect,-10.0,10.0) else glOrtho(-2.5*aspect,2.5*aspect,-2.5,2.5,-10.0,10.0); glMatrixMode(GL_MODELVIEW); end; procedure polygon_mode(value: integer); cdecl; begin case value of 1: begin glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glDisable(GL_BLEND); glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); end; 2: begin glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glColor3f(1.0,1.0,1.0); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); end; end; glutPostRedisplay(); end; procedure main_menu(value: integer); cdecl; begin if value=666 then begin glutDestroyWindow (oglWin); halt(0); end; end; (* Main Loop * Open window with initial window size, title bar, * RGBA display mode, and handle input events. *) var submenu: integer; begin glutInit (@argc,argv); glutInitWindowPosition(0,0); glutInitWindowSize(500,500); oglWin := glutCreateWindow('Demo'); myinit(); glutReshapeFunc(@myReshape); glutDisplayFunc(@display); submenu:= glutCreateMenu(@polygon_mode); glutAddMenuEntry('Filled',1); glutAddMenuEntry('Outline',2); glutCreateMenu(@main_menu); glutAddMenuEntry('Quit',666); glutAddSubMenu('Polygon mode',submenu); glutAttachMenu(GLUT_RIGHT_BUTTON); glutMainLoop(); end. ==== Blender ==== {{ articles:blender.png }} (*** << Blender >> Ported to Free Pascal by Romiras, Feb 2005 ***) {$apptype GUI} {$mode objfpc} Uses GL, GLU, GLUT; Type Arr3 = array [0..3] of GLfloat; Const light0_ambient: Arr3 = (0.2,0.2,0.2,1.0); light0_diffuse: Arr3 = (0.0,0.0,0.0,1.0); light1_diffuse: Arr3 = (1.0,0.0,0.0,1.0); light1_position: Arr3 = (1.0,1.0,1.0,0.0); light2_diffuse: Arr3 = (0.0,1.0,0.0,1.0); light2_position: Arr3 = (-1.0,-1.0,1.0,0.0); s: GLfloat = 0.0; angle1: GLfloat = 0.0; angle2: GLfloat = 0.0; var oglWin : integer; procedure output(x: GLfloat; y: GLfloat; text: pchar); var i: word; begin glPushMatrix(); glTranslatef(x,y,0); for i := 0 to strlen(text)-1 do glutStrokeCharacter(GLUT_STROKE_ROMAN, smallint(text[i])); glPopMatrix(); end; procedure display(); cdecl; const amb: array [0..3] of GLfloat=(0.4,0.4,0.4,0.0); dif: array [0..3] of GLfloat=(1.0,1.0,1.0,0.0); begin glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glEnable(GL_LIGHT1); glDisable(GL_LIGHT2); dif[3]:= cos(s) / 2.0 + 0.5; amb[3]:= dif[3]; glMaterialfv(GL_FRONT,GL_AMBIENT,amb); glMaterialfv(GL_FRONT,GL_DIFFUSE,dif); glPushMatrix(); glTranslatef(-0.3,-0.3,0.0); glRotatef(angle1,1.0,5.0,0.0); glCallList(1); glPopMatrix(); (* render ico display list *) glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_LIGHT2); glDisable(GL_LIGHT1); dif[3]:= 0.5 - cos(s*0.95) / 2.0; amb[3]:= dif[3]; glMaterialfv(GL_FRONT,GL_AMBIENT,amb); glMaterialfv(GL_FRONT,GL_DIFFUSE,dif); glPushMatrix(); glTranslatef(0.3,0.3,0.0); glRotatef(angle2,1.0,0.0,5.0); glCallList(1); glPopMatrix(); (* render ico display list *) glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,1500,0,1500); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glRotatef(4,0.0,0.0,1.0); (* Rotate text slightly to help show jaggies. *) output(200,225,'This is antialiased.'); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); output(160,100,'This text is not.'); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); glMatrixMode(GL_MODELVIEW); glutSwapBuffers(); end; function FMod(a,b: glFloat): glFloat; var x: Integer; begin x := Trunc (a / b); result := a - b * x; end; procedure idle(); cdecl; begin angle1:= fmod (angle1+0.8, 360.0); angle2:= fmod (angle2+1.1, 360.0); s += 0.5; glutPostRedisplay(); end; procedure visible(vis: integer); cdecl; begin if vis=GLUT_VISIBLE then glutIdleFunc(@idle) else glutIdleFunc(nil); end; procedure keyboard(key: byte; x ,y: longint); cdecl; begin case Chr(key) of #27: begin glutDestroyWindow (oglWin); halt(0); end; end; end; begin glutInit (@argc,argv); glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH); oglWin := glutCreateWindow('blender'); glutDisplayFunc(@display); glutVisibilityFunc(@visible); glutKeyboardFunc(@keyboard); glNewList(1,GL_COMPILE); glutSolidIcosahedron(); (* create ico display list *) glEndList(); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse); glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse); glLightfv(GL_LIGHT1,GL_POSITION,light1_position); glLightfv(GL_LIGHT2,GL_DIFFUSE,light2_diffuse); glLightfv(GL_LIGHT2,GL_POSITION,light2_position); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_LINE_SMOOTH); glLineWidth(2.0); glMatrixMode(GL_PROJECTION); gluPerspective(40.0,1.0,1.0,10.0); (* field of view in degree *) (* aspect ratio *) (* Z *) (* Z *) glMatrixMode(GL_MODELVIEW); gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0); (* eye is at (0,0,5) *) (* center is at (0,0,0) *) glTranslatef(0.0,0.6,-1.0); (* up is in positive Y direction *) glutMainLoop(); end. ==== Spinning cone demo ==== {{ articles:spincone.png }} (*** << Spinning cone demo >> Control: Space key - Turn On/Off spinning "+" key - increase speed "-" key - decrease speed NOTE: == C-like operators support == turn on in IDE: Options -> Compiler-> C-like operators or "-Sc" in command line Ported to Free Pascal by Romiras, Feb 2005 ***) {$apptype GUI} {$mode ObjFPC} {*** C-like operators support *** turn on in IDE: Options -> Compiler-> C-like operators or "-Sc" in command line ***} Uses GL, GLU, GLUT; var oglWin : integer; rotating : integer; (* to store if we're currently rotating *) rotx, roty, rotz : glFloat; (* the rotation to give our object *) // last_fps_time, // time_per_fps_disp, // framecount, oldtime, newtime : longint; rspeed, dt: single; function FMod(a,b: glFloat): glFloat; var x: Integer; begin x := Trunc (a / b); result := a - b * x; end; function delta_time: single; const CLOCKS_PER_SEC = 18.2; begin oldtime:= newtime; newtime:= glutGet (GLUT_ELAPSED_TIME); result:= (newtime - oldtime) / CLOCKS_PER_SEC; end; procedure init; const mat_specular: array [0..3] of GLfloat=(1.0,1.0,1.0,1.0); (* material definition *) (* material definition *) mat_shininess: array [0..0] of GLfloat=(50.0); (* another... *) (* another... *) light_position: array [0..3] of GLfloat=(1.0,1.0,1.0,0.0); LightPosition: array [0..3] of GLfloat=(0.0,0.0,2.0,1.0); LightDiffuse: array [0..3] of GLfloat=(1.0,1.0,1.0,1.0); // Значения диффузного света ( НОВОЕ ) begin glClearColor(0.1,0.2,0.1,0.0); glShadeModel(GL_FLAT); (* black and opaque *) glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular); (* GL_FLAT is faster, but if you have curved * surfaces, GL_SMOOTH is way prettier. *) glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess); (* apply the material *) glLightfv(GL_LIGHT0,GL_POSITION,light_position); (* definitions *) glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Установка Диффузного Света glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Позиция света glEnable(GL_LIGHTING); (* defien a light *) // glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); (* enable lighting in general *) glEnable(GL_DEPTH_TEST); (* enable the light we made *) glNewList (1, GL_Compile); glBegin(GL_TRIANGLES); glNormal3f(1,1,-1); glVertex3f(1,0,0); glVertex3f(0,1,0); glVertex3f(0,0,-1); glEnd; glBegin(GL_TRIANGLES); glNormal3f(-1,1,-1); glVertex3f(-1,0,0); glVertex3f(0,1,0); glVertex3f(0,0,-1); glEnd; glBegin(GL_TRIANGLES); glNormal3f(-1,1,1); glVertex3f(-1,0,0); glVertex3f(0,1,0); glVertex3f(0,0,1); glEnd; glBegin(GL_TRIANGLES); glNormal3f(1,1,1); glVertex3f(1,0,0); glVertex3f(0,1,0); glVertex3f(0,0,1); glEnd; glEndList; rspeed:= 0.04; end; (* function to run when the window is reshaped (set up viewport) *) procedure reshape(w: integer; h: integer); cdecl; var aspratio: GLfloat; begin glViewport(0,0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); aspratio := GLfloat(h)/GLfloat(w); if w<=h then glOrtho(-1.5,1.5, -1.5*aspratio, 1.5*aspratio, -10.0, 10.0) else glOrtho(-1.5*aspratio, 1.5*aspratio, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); end; (* function to draw stuff in graphic context *) procedure display; cdecl; begin dt := delta_time (); glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); (* this one clears the gl scene *) if rotating<>0 then begin (* update the rotation, with bounds checking *) (* % doesn't like glFloats... so we cast to int and cast * back after the modulus. the % keeps the number * bounded between [0,360). (No, that's not a type, * that's math notation for inclusive and exclusive *) rotx:= FMod(rspeed*30.0*dt+rotx, 360.0); roty:= FMod(rspeed*45.0*dt+roty, 360.0); rotz:= FMod(rspeed*60.0*dt+rotz, 360.0); end; glLoadIdentity(); glRotatef(rotx,1,0,0); glRotatef(roty,0,1,0); glRotatef(rotz,0,0,1); glColor3f(1.0,0.0,0.0); glCallList (1); glColor3f(1.0,0.0,1.0); (* remembers, another important operation is * glTranslatef(). If you want to rotate or * move one thing and have it not effect the * other objects in the scene, you can use * glPushMatrix() before the operations and * glPopMatrix() after the operations. *) glutSwapBuffers(); (* draw a cube :) *) end;(* actually display it (doublebuffer style) *) (* keyboard callback *) procedure keyboard(key: byte; x: integer; y: integer); cdecl; begin case Chr(key) of #27: (* escape exits *) begin glutDestroyWindow (oglWin); halt(0); end; ' ': rotating:= rotating xor 1; (* space toggles 'rotating' *) '+': rspeed += 0.01; '-': rspeed -= 0.01; end; if rspeed>2.0 then rspeed:= 2.0; if rspeed<-2.0 then rspeed:= -2.0; end; procedure OnTimer(value: Integer); cdecl; begin glutPostRedisplay; glutTimerFunc(20, @OnTimer, 0); end; begin glutInit(@argc,argv); glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH); glutInitWindowSize(400,400); oglWin := glutCreateWindow('GLUT demo'); init(); glutDisplayFunc(@display); // define the callbacks glutReshapeFunc(@reshape); glutKeyboardFunc(@keyboard); glutTimerFunc(20, @OnTimer, 0); glutMainLoop(); end.