آموزش کاربردی OpenGL در دلفی ...
سلام دوستان ...
تصميم گرفتم آموزش OpenGL رو به صورت کاربردي شروع کنم ...
من توي يه پست ديگه هم قبلا آموزش رو تا يه جاهايي نوشته بودم ولي چون اون پست شلوغ شد و ديگه کم کم داشت Down مي شد ، گفتم که يه پست جديد بدم و از ابتدا شروع کنم ...
خوب ...
براي آشنايي مقدماتي با OpenGL به لينک زير بريد :
ادامه بحث :
در ابتدا طريقه ساخت يک پنجره مخصوص OpenGL رو آموزش مي دم : ( نکته مهم : براي هرگونه استفاده از توابع و رسم اشکال 2 بعدي يا 3 بعدي با OpenGL بايد پنجره نخصوص اون رو ايجاد کنيد )
خوب ...
مراحل اين کار :
1. ايجاد DC
2. برپايي فرمت نقطه اي
3. ايجاد RC
نکته مهم : در هنگام خروج از برنامه بايد DC و RC ساخته شده را حذف نماييم که بعدا بحث خواهيم کرد ...
خوب در ابتدا بايد چند پروسجر رو به فرم برنامتون اضافه کنيد :
1. پروسجر CleanUp که براي پاک کردن DC و RC به کار مي ره :
کد:
procedure CleanUp(Handle: HDC);
begin
if hrc<> 0 then
begin
if (not wglMakeCurrent(handle,0)) then
MessageBox(0,'آزاد کردن DC و RC با خطا مواجه شد'
,'خطاي خروج',MB_OK or MB_ICONERROR);
if (not wglDeleteContext(hRc)) then
begin
MessageBox(0,'آزاد سازي بافت هاي رندر شده با خطا مواجه شد.',
' خطاي خروج',MB_OK or MB_ICONERROR);
hRc:=0;
end;
end;
end;
در پروسجر بالا ، DC و RC را حذف مي کنيم و در صورتي که با خطا مواجه شويم پيغامي ظاهر خواهد شد ...
2. پروسجر InitGL براي شروع به کار پنجره مخصوص :
کد:
procedure InitGL;
begin
// select clearing color
glClearColor( 0, 0, 0, 0);
// initialize viewing values
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho( 0, 1, 0, 1, -1, 1);
end;
در پروسجر بالا از سه تابع استفاده شده :
( 1. glClearColor : براي تعيين رنگ به کار مي رود
2. glMatrixMode : اين تابع ماتريس جاري را تعيين مي کند ( از ماتريسها براي تعيين مکان اشياء و مکان دوربينها استفاده مي شود که سه مقدار دارد : GL_MODELVIEW که ماتريس پيشفرض مي باشد، GL_PROJECTION و GL_TEXTURE .
البته تابع ديگري هم استفاده شده به نام glLoadIdentity که ماتريس قابل تغيير فعلي رو به ماتريس اصلي و واحد تبديل مي کنه )
3. glOrtho : که ديد سه بعدي براي اشياء را فراهم مي کند )
3. پروسجر DrawGLScene که براي ايجاد قابليت رسم و رسم استفاده مي شود :
کد:
procedure DrawGLScene();
begin
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 1, 0, 1, -1, 1);
glColor3f(1.0, 1.0, 1.0);
glBegin (GL_POLYGON);
glVertex3f (0.25, 0.25, 0);
glVertex3f (0.75, 0.25, 0);
glVertex3f (0.75, 0.75, 0);
glVertex3f (0.25, 0.75, 0);
glEnd;
glFlush;
end;
در پروسجر بالا هم ابتدا قابليت GL_DEPTH_TEST ( مربوط به عمق مي شود و با 39 مقدار ديگر قابل تغير است ) به برنامه اضافه مي شود و در آخر هم توابعي براي رسم به کار رفته است ...
اگر توجه کنيد از تابع glVertex3f براي رسم استفاده شده است که تمام آنها بين بلوکهاي Begin و end قرار گرفته اند ...
براي رسم اشياء بايد نام آنها را در قسمت Brgin وارد کرده و سپس شروع به رسم کنيم و سپس با بلوک end به رسم خود پايان دهيم ...
از تابع glFlush که در پايان آمده هم براي اطمينان از صحت رسم استفاده مي شود ...
خوب ...
4. پروسجر SetDCPixelFormat که براي ترسيم فرمت نقطه اي استفاده مي شود ...
کد:
procedure SetDCPixelFormat(Handle: HDC;ColorBits,DepthBufferBits:integer);
var
pfd: TPixelFormatDescriptor;
nPixelFormat: Integer;
begin
FillChar(pfd, SizeOf(pfd), 0);
with pfd do begin
nSize := sizeof(pfd); // Size of this structure
nVersion := 1; // Version number
dwFlags := PFD_SUPPORT_OPENGL Or PFD_DRAW_TO_WINDOW
Or PFD_TYPE_RGBA; // Flags
iPixelType:= PFD_TYPE_RGBA; // RGBA pixel values
cColorBits:= ColorBits; // 24-bit color
cDepthBits:= DepthBufferBits; // 32-bit depth buffer
iLayerType:= PFD_MAIN_PLANE; // Layer type
end;
nPixelFormat := ChoosePixelFormat(Handle, @pfd);
//Did We Find A Matching Pixelformat?
if (nPixelFormat=0) then
begin
CleanUp(handle); //Reset The Display
MessageBox(0,'Cant''t Find A Suitable PixelFormat.'
,'Error',MB_OK or MB_ICONEXCLAMATION);
end;
//Are We Able To Set The Pixelformat?
if (not SetPixelFormat(Handle, nPixelFormat, @pfd)) then
begin
CleanUp(handle); //Reset The Display
MessageBox(0,'Cant''t set PixelFormat.'
,'Error',MB_OK or MB_ICONEXCLAMATION);
Halt(1); { Halt right here! }
end;
hrc := wglCreateContext(Handle);
if (hRc=0) then
begin
CleanUp(handle); //Reset The Display
MessageBox(0,'Cant''t create a GL rendering context.'
,'Error',MB_OK or MB_ICONEXCLAMATION);
Halt(1); { Halt right here! }
end;
//Are We Able To Activate The Rendering Context?
if (not wglMakeCurrent(Handle, hrc)) then
begin
CleanUp(handle); //Reset The Display
MessageBox(0,'Cant''t activate the GL rendering context.'
,'Error',MB_OK or MB_ICONEXCLAMATION);
Halt(1); { Halt right here! }
end;
چون در پروسجر بالا از توابع اي استفاده شده که قبلا توضيح داده شد ، ديگه از توضيح اونها صرف نظر مي کنيم ( با کمي نگاه کردم به کد مي تونيد کارش رو بفهميد ، البته اگه سئوالي پيش اومد حتما بپرسيد )
خوب پروسجرها تمام شدن ، حال مي ريم روي فرم تا رويدادهاش رو تنظيم کنيم :
اول در خاصيت FormCreate کد زير رو بنويسيد :
کد:
f_Hdc:=GetDC(Handle);
// ساخت بافت رندر
SetDCPixelFormat(f_Hdc,16,16);
InitGL;
بعد در خاصيت FormDestroy کد زير رو بنويسيد :
بعد در خاصيت FormPaint کد زير رو بنويسيد :
کد:
wglMakeCurrent(f_Hdc,hrc); //activate the RC
DrawGLScene;
حالا در خاصيت FormResize کد زير رو بنويسيد و تمام :
کد:
// Redefine the viewing volume and viewport
//when the window size changes.
wglMakeCurrent(f_Hdc, hrc);
// Reset The Current Viewport And Perspective
// Now, set up the viewing area-select the full client area
glViewport( 0, 0, Width , Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluOrtho2D(0, Width, 0, Height);
DrawGLScene();
توجه : دستورات hrc: HGLRC و f_Hdc : LongInt را در قسمت Var در اول کدهاي فرم به عنوان متغير تعريف کنيد ...
حالا ديگه تموم شد ...
البته ما در کدهاي بالا از توابعي استفاده کرديم که کامل توضيح داده نشدن ، ولي در پست بعدي فقط در مورد توابع و کاربردهاي اونها صحبت مي کنيم ...
موفق باشيد ...