OpenGL development in Delphi entry (turn)

xiaoxiao2021-03-06  14

OpenGL development in Delphi entry (turn)

2004-4-25 | 13:35 (GMT 0)

Original address: http://bdn.borland.com/Article/0,1410,26401,00.html Overview: This article is like a recipe that teaches people to cook, so that Delphi developers get an effective knowledge of OpenGL 3D graphics programming. . Author: Alex SemichastnyOpenGL specification was originally developed by Silicon Graphics underlying graphics library. The part of this specification is accurately implemented in your system, which is often referred to as OpenGL driver, which allows you to describe the scene you want to perform using geometric collection (point, line, polygon, image, etc.). Let the naked eye to observe a more comfortable medium-sized scenario, usually in millisecond speed, which means that the library file has sufficient ability to support you to create a vibrant virtual world. OpenGL drivers are typically provided in the form of binary library files. It can dynamically connect to your program. On the Windows platform, it will be in the form of a DLL (check OpenGL.DLL in your system directory). Since Delphi can use any DLL, it is as easy as OpenGL 3D programming is like any other language. This article will help you get effective knowledge of OpenGL development in Delphi. The mathematical foundation OpenGL has a powerful mathematical foundation, so the limitations of its function depends entirely on your imagination (translator's note: not doing, only thinking). It is better to understand those axioms and inexplicers, and let us immediately know a simple 3D coordinate system, which is a coordinate system in 3D programming. As follows: How should you understand your screen (blue square) placed in the scene? Issue four rays and form the point of the screen, which is the point of view in the imagination space. OpenGL let you call two simple functions to define this scene GLmatrixMode (GL_Projection); GLFRUSTUM (-0.1, 0.1, -0.1, 0.1, 0.3, 25.0); -0.1, 0.1, -0.1 during this calling process, 0.1 Defines the top left corner of this visual screen and the lower right corner; 0.3 Specify the distance from the screen to the screen (just "Near Clipboard") at the same time 25.0 Specify "Far Clipping Plate" (FAR CLIPPING PLANE) . An object in front of any near clipboard and the object behind the far shear plate will be invisible. Of course, you can settle these numbers to make them suitable for the scene you need. From the basic element to the object, the most interesting part is now: object. OpenGL only supports the following basic geometry: points, lines and polygons. No surface or more advanced graphics (such as spherical graphics) can be drawn as a basic graphic element. But they can imitate the perfect way with polygons. Will look at modern 3D games, you will find that they are completely established by triangles. Therefore, we will not be constrained by this restriction. The drawing of objects is very similar to Pascal language programming. Each block should be included by Begin-End, more specifically, glbegin () and glend (). As with the following example: const S = 1.0; d = 5.0; ... glbegin (GL_TRIANGLES); GlvertEX3F (-S, 0, d); GlvertEX3F (S, 0, D); GlvertEX3F (0, S, D); This is a simple triangle. It has 5 units from your point of view, one unit, 2 units wide. This is a screenshot: even if it looks not like 3D graphics, it is our initial block. In the following you can see the source code of this example. Before you start drilling the code, there are some words to say. Each OpenGL programming includes some OS-Specific code for initializing the output device. If you use Win32, you will need to set the pixel format and create a display context environment to leave the Windows device context environment.

If you are not very in Windows system level programming, you can use the following code as a template. Details of the called function in FormCreate can refer to the help documentation.

FILE: Tri.pasunit Tri; interfaceuses OpenGL, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls; type TForm1 = class (TForm) procedure FormCreate (Sender: TObject); procedure FormPaint ( Sender: TObject); private procedure Draw; // Draws an OpenGL scene on request public end; var Form1: TForm1; implementation {$ R * .DFM} procedure setupPixelFormat (DC: HDC); const pfd: TPIXELFORMATDESCRIPTOR = (nSize: sizeof (TPIXELFORMATDESCRIPTOR); // size nVersion: 1; // version dwFlags: PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER; // support double-buffering iPixelType: PFD_TYPE_RGBA; // color type cColorBits: 24; // preferred color depth cRedBits: 0; cRedShift : 0; // Color Bits (Ignored) CGreenBits: 0; CGreenshift: 0; CBLueBits: 0; Clueshift: 0; Calphabits: 0; CalphaBits: 0; Calphashift: 0; // no alpha buffer caccumbits: 0; caccumredbits: 0; // no Accum ulation buffer, cAccumGreenBits: 0; // accum bits (ignored) cAccumBlueBits: 0; cAccumAlphaBits: 0; cDepthBits: 16; // depth buffer cStencilBits: 0; // no stencil buffer cAuxBuffers: 0; // no auxiliary buffers iLayerType: PFD_MAIN_PLANE; // main layer bReserved: 0; dwLayerMask: 0; dwVisibleMask: 0; dwDamageMask: 0; // no layer, visible, damage masks); var pixelFormat: integer; begin pixelFormat: = ChoosePixelFormat (DC, @pfd); IF (Pixelformat = 0) THEN EXIT; IF (setpixelformat (dc, pixelformat, @PFD) <> true) THEN EXIT; End; Procedure Glinit; Begin // Set Viewing Projection GlmatrixMode;

GLFRUSTUM (-0.1, 0.1, -0.1, 0.1, 0.3, 25.0); // Position Viewer Glmatrixmode (GL_MODELVIEW); GLENABLE (GL_DEPTH_TEST); End; Procedure TFORM1.FormCreate (Sender: TOBJECT); var DC: HDC; RC: HGLRC; i: integer; begin DC: = GetDC (Handle); // Actually, you can use any windowed control here SetupPixelFormat (DC); RC: = wglCreateContext (DC); // makes OpenGL window out of DC wglMakeCurrent (DC , RC); // makes OpenGL window active GLInit; // initialize OpenGLend; procedure TForm1.Draw; const S = 1.0; D = 5.0; begin glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; glTranslatef (0.0, 0.0, -12.0) Glbegin (GL_TRIANGLES); GLVERTEX3F (-S, 0, D); GlvertEX3F (S, 0, D); GLVERTEX3F (0, S, D); GLEND; SWAPBuffers (WGlgetCurrentDC); End; Procedure TFORM1.FormPaint (Sender: TOBJECT); begin Draw; end; end.file: tri.dfmobject form1: tform1 border = bsdialog caption = / 'Basic OpenGL Program /' ClientHeight = 318 ClientWidth = 373 Oncreate = FormCreate OnPaint = FormPaintend 3D Adventures, let us start real 3D. Plate the previous code as a framework, we add some code line code to establish a tetrahedron with a shadow. How should I build it with basic graphical elements? We use four triangles. One is at the bottom and the other three as the side.

Here is to generate their code: procedure tform1.draw; const D = 1.5; H1 = D / 1.732; H2 = D * 1.732-H1; // d / h = Tg (30) = 1 / sqrt (3) HY = 3.0; const // Vertexes A1: Tglarrayf3 = (- D, 0, -H1); // Bootom Left A2: TglarrayF3 = (D, 0, -H1); // Bootom Right A3: Tglarrayf3 = (0, 0, H2); // bootom back a4: TGLArrayf3 = (0, HY, 0); // topbegin glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity; glTranslatef (0.0, 0.0, -12.0); glBegin (GL_TRIANGLES); glVertex3fv (@ a1 ); GLVERTEX3FV (@ a3); GlvertEX3FV (@ A2); GlvertEX3FV (@ A1); GlvertEX3FV (@ a2); GlvertEX3FV (@ a4); glvertex3fv (@ A3); GlvertEX3FV (@ a3); GlvertEx3fv (@ a3); GlvertEX3FV (@ a3); GlvertEX3FV (@ a1); GlvertEX3FV (@ a4); glend; swapbuffrs (wglgetcurrentdc); END; although it looks a bit complicated, it is easy to understand when you face the picture below. . We define vertices A1 - A4 to establish a specified triangle according to the 4 vertical positions. When you define your triangle (or other polygons), use the following rules: Always arrange the fixed-point serial number in the counterclockwise order, just like you are watching the side. Through this rule, we can specify the designated A1-A2-A4, A1-A3-A2 (looking up), A2-A3-A4 and A3-A1-A4. Now replace Tri.PAS in the TFORM1.DARW () section, the effect of the program run does not reflect too much change. It looks still unlike three-dimensional graphics. This is because we haven't set any light sources yet. Lights! Camera! OpenGL! There are two parts in OpenGL in OpenGL: light source itself (color, strength, etc.) and object material. Material, in turn, including colors, some physical parameters (such as opacity gloss) and texture. In-depth, this will be a huge world, we will approach step by step. Define a light source is quite easy.

procedure GLInit; const light0_position: TGLArrayf4 = (-8.0, 8.0, -16.0, 0.0); ambient: TGLArrayf4 = (0.3, 0.3, 0.3, 0.3); begin // set viewing projection glMatrixMode (GL_PROJECTION); glFrustum (-0.1, 0.1, -0.1, 0.1, 0.3, 25.0); // position viewer * / glMatrixMode (GL_MODELVIEW); glEnable (GL_DEPTH_TEST); // set lights glEnable (GL_LIGHTING); glLightfv (GL_LIGHT0, GL_POSITION, @ light0_position); glLightfv (GL_LIGHT0 , GL_AMBIENT, @ambient; glenable (GL_Light0); END; two constants within the code are must be. A defined source position (located on the left corner of the viewpoint) and another define ambient light. This will produce a small amount of scattered light so that you can see some objects that are fully located in the shadow. Although you can use light to set the light source, it is still not drawing shadows. This is because OpenGL needs to know how the "Normal" of each polygon you specify is for light calculations (Normal is a vector that is orthogonal to the surface). If you don't have your own vector function library, you can use the following methods to calculate Normal of the three vertices in the triangle. This function is based on a fixed point counterclockwise row, because Normal is a vector fork, and if you don't follow this rule, the vector points to the interior of the tetracene.

Function GetNormal (P1, P2, P3: Tglarrayf3): Tglarrayf3; Var A, B: Tglarrayf3; Begin // Make Two Vectors A [0]: = P2 [0] -p1 [0]; a [1]: = p2 [1] -p1 [1]; A [2]: = p2 [2] -p1 [2]; b [0]: = p3 [0] -p1 [0]; b [1]: = p3 [1 ] -p1 [1]; B [2]: = p3 [2] -p1 [2]; // Calculate Cross-Product Result [0]: = a [1] * b [2] -a [2] * B [1]; Result [1]: = a [2] * b [0] -A [0] * b [2]; result [2]: = a [0] * b [1] -a [1 ] * b [0]; end; use this function, you can set all the necessary information necessary to calculate the light: procedure tform1.draw; const D = 1.5; H1 = D / 1.732; H2 = D * 1.732-H1; // d / h = Tg (30) = 1 / sqrt (3) HY = 3.0; const // Vertexes A1: Tglarrayf3 = (- D, 0, -H1); A2: TGLARRAYF3 = (D, 0, -H1 ); A3: Tglarrayf3 = (0, 0, h2); A4: Tglarrayf3 = (0, hy, 0); VAR N1, N2, N3, N4: Tglarrayf3; // NormalsBegin N1: = GetNormal (A1, A3, A2 N2: = GetNormal (A1, A2, A4); N3: = GetNormal (A2, A3, A4); N4: = GetNormal (A3, A1, A4); GLCLEAR (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); GLENABLE (GL_NORMALIZE); Glshademodel (GL_FLAT); GLCULLFACE (GL_BACK); GLLOADIDENTITY; GLTRANSLATEF (0.0, 0.0, -12.0); Glbegin (GL_TRIANGLES); GLNORMAL3FV (@ n1); glvertex3fv (@ a1); GlvertEX3FV (@ a2); Glvertex3FV (@ a3); glNORMAL3FV (@ n2); glvertex3fv (@ a1); Glvertex3FV (@ a2); GlnorMal3FV @ n3); GlvertEX3FV (@ a2); GlvertEX3FV (@ a3); Glvertex3FV (@ a4); glNORMAL3FV (@ n4); glvertex3fv (@ a3); GlvertEX3FV (@ a1); glend; swapbuffers WGlgetCurrentDC); END; This is the effect of the above code: now, using something provided by a Delphi VCL.

转载请注明原文地址:https://www.9cbs.com/read-49271.html

New Post(0)