Topic này đưa các bài tutor về OpenGL, đề nghị kô chát chit ở đây hén.
Topic này đưa các bài tutor về OpenGL, đề nghị kô chát chit ở đây hén.
PROGRAM T(NewbieToNewBie);
USES Windows,
Messages,
OpenGL;
CONST
//Cái title này dùng để làm...title, he he, cái caption bên trên WindowApp của bạn đó.
WindowTitle = 'Newbie to newbie: Tutor 1';
//Tôi kô dùng cấu trúc form có sẵn vì nghĩ nó kô cần thiết, tôi dùng một số hàm API để tạo
//ra một Window mới, lớp Window này lấy định danh là:
WindowClass = 'CrazyBabeTutor';
CONST
//Những hằng số này để định nghĩa kiểu Window mới sẽ tạo ra
//Window kô có frame (no clothes, he he)
WindowNoFrame = $0001;
//Window kô có các button, khỏi click pậy
WindowNoButtons = $0010;
//Window kô có nút minimize, maximize
WindowNoMinMax = $0100;
//Window kiểu Tool, cái kiểu frame be bé xinh xinh đó mờ.
WindowTool = $1000;
TYPE
TNewBieEngine = Class
Private
HWindow : HWnd;
HDCHandle : HDC;
HRCHandle : HGLRC;
FullScreen : Boolean;
Finished : Boolean;
DemoTex : GLUInt;
//Xoá sổ chú Window đã được tạo ra
Procedure KillWindow;
//Resize, thực ra là thiết lập một số cấu hình của window để OpenGL hiển thị đúng cách.
Procedure ReSizeWindow(SizeW,SizeH : Integer);
//Bắt đầu vẽ thôi
Procedure BeginRender;
//Kết thúc >> chuyển ra màn hình hiển thị
Procedure EndRender;
//Bắt thông điệp của Window
Procedure PeekMessages;
Public
Constructor Create;
Destructor Destroy; OverRide;
//Khởi tạo window mới với kích thước SizeW x SizeH, độ sâu màu là PixelDepth (16, 24, 32, chớ có dại mà thử 8 hén).
//Flags là một cờ định nghĩa kiểu Window sẽ được tạo ra (WindowNoFrame, WindowNoButtons...)
//FullScreen: Có chiếm toàn màn hình kô nhể ? Cái này đồng nghĩa với việc bạn khởi tạo lại chế độ màn hình thành
//SizeW x SizeH, mặc định giá trị của nó là False.
Function Setup(SizeW,SizeH : Integer;
PixelDepth,Flags : Integer;
FullScreen : Boolean = False) : Boolean;
//Tạo một texture, gọi nôm na là vật liệu (đừng nhầm với material) có kích thước SizeW x SizeH từ khối dữ liệu PData
//Format nhận 1 trong 2 giá trị GL_RGBA (định nghĩa sẵn của OpenGL) hoặc something else. Có nghĩa là tạo ra một
//texture với độ sâu màu là 32bit hoặc 24bit.
Function CreateTexture(SizeW,SizeH,Format : Word;PData : Pointer) : Integer;
//Đọc texture từ 1 file BMP kô nén, các bạn có thể sửa lại dùng TBitmap để có thể đọc được các format khác nữa
Function LoadTexture(FileName : String;Var Texture : GLUInt) : Boolean;
//Xử lý chút đỉnh
Procedure Process;
//Vẽ pậy tí chơi
Procedure Drawing;
//Chạy hén ?
Procedure Running;
End;
VAR
//Mảng keys này lưu giữ phím nào bị press
Keys : Array[0..255] of Boolean;
NewBieEngine : TNewBieEngine;
//Mí hàm này cũng là chuẩn của OpenGL, GLU nhưng mờ thư viện của Delphi kô khai báo sẵn
//nên đành fải khai báo lại
PROCEDURE GLBindTexture(Target : GLEnum;Texture : GLUInt); StdCall; External OpenGL32 Name 'glBindTexture';
FUNCTION GLUBuild2DMipmaps(Target : GLEnum;Components,SizeW,SizeH : GLInt;Format,AType : GLEnum;
Data : Pointer): GLInt; StdCall; External GLU32 Name 'gluBuild2DMipmaps';
PROCEDURE GLGenTextures(N : GLSizeI;Var Textures : GLUInt); StdCall; External OpenGL32 Name 'glGenTextures';
CONSTRUCTOR TNewBieEngine.Create;
Begin
Inherited Create;
FullScreen:=False;
Finished:=False;
End;
DESTRUCTOR TNewBieEngine.Destroy;
Begin
KillWindow;
End;
//Hàm chặn Window messages
FUNCTION WindowHandleProc(HWnd : HWnd;Msg : UInt;WParam : WParam;LParam : LParam) : LResult; StdCall;
Begin
Case Msg of
WM_PAINT,
WM_CREATE,
WM_SIZE :
Begin
Result:=0;
End;
WM_CLOSE :
Begin
PostQuitMessage(0);
Result:=0
End;
WM_KEYDOWN:
Begin
Keys[WParam]:=True;
Result:=0;
End;
Else Result:=DefWindowProc(HWnd,Msg,WParam,LParam);
End;
End;
FUNCTION TNewBieEngine.Setup(SizeW,SizeH : Integer;
PixelDepth,Flags : Integer;
FullScreen : Boolean = False) : Boolean;
Var WndClass : TWndClass;
DWStyle,DWExStyle : DWord;
DMScreenSettings : DevMode;
XPos,YPos,PixelFormat : Integer;
H_Instance : HInst;
PFD : TPixelFormatDescriptor;
Begin
Self.FullScreen:=FullScreen;
H_Instance:=GetModuleHandle(Nil);
//Cấu hình thông tin để đăng kí một lớp cửa sổ mới
ZeroMemory(@WndClass,SizeOf(WndClass));
With WndClass do
Begin
Style:=CS_HREDRAW or CS_VREDRAW or CS_OWNDC;
LPFNWndProc:=@WindowHandleProc;
HInstance:=H_Instance;
HCursor:=LoadCursor(0,IDC_ARROW);
LPSZClassName:=WindowClass;
End;
//Cóc đăng kí được ? Đành thôi zậy
If RegisterClass(WndClass)=0 then
Begin
Result:=False;
Exit
End;
//Nếu muốn full screen ?
If FullScreen then
Begin
//Cấu hình thông tin để khởi tạo lại chế độ màn hình
ZeroMemory(@DMScreenSettings,SizeOf(DMScreenSettin gs));
With DMScreenSettings do
Begin
DMSize:=SizeOf(DMScreenSettings);
DMPelsWidth:=SizeW;
DMPelsHeight:=SizeH;
DMBitsPerPel:=PixelDepth;
DMFields:=DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
End;
//Cóc thay được (lỗi, kô hỗ trợ...) ? Đành thôi, nhưng kô đến nỗi fải halt
//Có thể tạm chấp nhận chạy kô full screen
If ChangeDisplaySettings(DMScreenSettings,CDS_FULLSCR EEN)=
DISP_CHANGE_FAILED then FullScreen:=False;
End;
//Nếu full screen thì kô cần quan tâm đến kiểu của Window
If FullScreen then
Begin
DWStyle:=WS_POPUP or WS_CLIPCHILDREN or WS_CLIPSIBLINGS;
DWExStyle:=WS_EX_APPWINDOW or WS_EX_TOPMOST;
ShowCursor(False);
End
Else
//Còn nếu kô, setup một xí
Begin
Case Flags of
WindowNoFrame :
Begin
DWStyle:=WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
DWExStyle:=WS_EX_APPWINDOW;
End;
WindowNoButtons :
Begin
DWStyle:=WS_CAPTION or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
DWExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
End;
WindowTool :
Begin
DWStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
DWExStyle:=WS_EX_TOOLWINDOW or WS_EX_WINDOWEDGE;
End;
WindowNoMinMax :
Begin
DWStyle:=WS_SYSMENU or WS_CAPTION or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
DWExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
End;
Else
Begin
DWStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
DWExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
End;
End;
End;
//Chuyển window "đứng" giữa màn hình cho .. oai hén
XPos:=(GetSystemMetrics(SM_CXSCREEN)-SizeW) ShR 1;
YPos:=(GetSystemMetrics(SM_CYSCREEN)-SizeH) ShR 1;
//Tạo một window mới
HWindow:=CreateWindowEx(DWExStyle,WindowClass,Wind owTitle,DWStyle,
XPos,YPos,SizeW,SizeH,0,0,H_Instance,Nil);
//Lại cóc tạo được ? Bull****, thôi nhé chào iem.
If HWindow=0 then
Begin
KillWindow;
Result:=False;
Exit;
End;
//Cóc lấy được handle ? Đành thôi.
HDCHandle:=GetDC(HWindow);
If HDCHandle=0 then
Begin
KillWindow;
Result:=False;
Exit;
End;
With PFD do
Begin
NSize:=SizeOf(TPIXELFORMATDESCRIPTOR);
NVersion:=1;
DWFlags:=PFD_DRAW_TO_WINDOW or
PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER;
IPixelType:=PFD_TYPE_RGBA;
CColorBits:=PixelDepth;
CRedBits:=0;
CRedShift:=0;
CGreenBits:=0;
CGreenShift:=0;
CBlueBits:=0;
CBlueShift:=0;
CAlphaBits:=0;
CAlphaShift:=0;
CAccumBits:=0;
CAccumRedBits:=0;
CAccumGreenBits:=0;
CAccumBlueBits:=0;
CAccumAlphaBits:=0;
CDepthBits:=16;
CStencilBits:=0;
CAuxBuffers:=0;
ILayerType:=PFD_MAIN_PLANE;
BReserved:=0;
DWLayerMask:=0;
DWVisibleMask:=0;
DWDamageMask:=0;
End;
PixelFormat:=ChoosePixelFormat(HDCHandle,@PFD);
If PixelFormat=0 then
Begin
KillWindow;
Result:=False;
Exit;
End;
If Not SetPixelFormat(HDCHandle,PixelFormat,@PFD) then
Begin
KillWindow;
Result:=False;
Exit;
End;
HRCHandle:=WGLCreateContext(HDCHandle);
If HRCHandle=0 then
Begin
KillWindow;
Result:=False;
Exit;
End;
If Not WGLMakeCurrent(HDCHandle,HRCHandle) then
Begin
KillWindow;
Result:=False;
Exit;
End;
ShowWindow(HWindow,SW_SHOW);
SetForeGroundWindow(HWindow);
SetFocus(HWindow);
//Thiết lập một số thông số của OpenGL
ReSizeWindow(SizeW,SizeH);
//Thiết lập màu xoá màn hình, màu này gồm 4 thành phần R, G, B, A (cái này chắc các bạn biết rùi)
//Chỉ có hơi khác là nó dùng số thực để chỉ thị. Giới hạn từ 0 đến 1. Nếu vẫn muốn dùng số nguyên
//cho quen thì làm một fép chia là được.
GLClearColor(0,0,0,0.0);
//Đổ bóng mịn mịn chút nhé ku
GLShadeModel(GL_SMOOTH);
//Thiết lập xoá DepthBuffer
//Nói qua một chút về DepthBuffer:
// Đây là một kĩ thuật tương đối hay ho để vẽ những vật thể 3D kô bị lỗi. Giả sử bạn vẽ một chú rùi,
//sau đấy là vẽ một thằng sau nó hoặc là cắt cắt zới nó một chút, làm seo để hình ảnh kô bị chồng lấp
//lên nhau đây ? Kĩ thuật này đề ra một giải pháp tương đối đơn giản mà chấp nhận được: Đánh toạ độ Z
//(chiều thứ 3) cho những điểm "đã vẽ rồi", thế là khi vẽ một điểm 3D mới, chỉ cần tính tương đối với
//Z-buffer thì sẽ cho ngay là có "nên" vẽ nó kô. Mà cái này thực hiện bằng phần cứng là chính nên bạn
//kô cần fải lo :>, chỉ cần biết khái niệm đơn giản như zậy là được, nhưng đừng bỏ qua vì sau này sẽ
//có rất nhìu ziệc cần động chạm đến thằng này.
GLClearDepth(1.0);
//Đây là định nghĩa hàm so sánh trong Z-Buffer đó, nếu điểm mới có toạ độ nhỏ hơn điểm đã vẽ trước đó
//thì vẽ, or else thì thôi. DepthFunc hỗ trợ các hàm GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL,
//GL_GEQUAL, GL_GREATER, GL_NOTEQUAL tương ứng với chẳng bao giờ vẽ (?), luôn vẽ, vẽ nếu Z bé hơn, vẽ nếu
//Z bé hơn hoặc bằng, vẽ nếu Z bằng, vẽ nếu Z lớn hơn hoặc bằng, vẽ nếu Z lớn hơn, vẽ nếu Z khác nhau.
//Chú ý là những tham số này cũng dùng cho một số hàm chỉ định khác chứ kô fải chỉ cho GLDepthFunc
GLDepthFunc(GL_LESS);
//Định nghĩa factor cho hàm blending, nói sơ một chút mặc dù chưa sử dụng ở đây (He he, kô được hệ thống
//lém, nhỉ ?) những factor này hiệu quả khi bạn vẽ trong chế độ blending (Bật bằng GLEnable(GL_BLEND))
//Khi vẽ trong chế độ này điểm màu được vẽ sẽ được tính bằng công thức sau:
// Màu nguồn * Source Factor + Màu đích * Dest Factor
//Công thức này áp dụng cho từng kênh màu R,G,B và kênh alpha.
//Ở đó màu nguồn là màu của vật thể được vẽ hoặc màu điểm ảnh texture tương ứng được áp lên, còn màu đích
//dĩ nhiên là màu điểm đã được vẽ lên rồi.
//Còn Source Factor và Dest Factor ? Chúng được tham chiếu qua bảng sau:
// Kiểu Giá trị
// GL_ZERO = 0 (Dùng cho source or dest factor)
// GL_ONE = 1 (Dùng cho source or dest factor)
// GL_DST_COLOR = Màu đích (Dùng cho source factor)
// GL_SRC_COLOR = Màu nguồn (Dùng cho dest factor)
// GL_ONE_MINUS_DST_COLOR = 1-Màu đích (Dùng cho source factor)
// GL_ONE_MINUS_SRC_COLOR = 1-Màu nguồn (Dùng cho dest factor)
// GL_SRC_ALPHA = Giá trị kênh Alpha của nguồn (Dùng cho source or destination)
// GL_ONE_MINUS_SRC_ALPHA = 1- kênh alpha của nguồn (Dùng source or destination)
// GL_DST_ALPHA = Kênh alpha của đích (Dùng source or destination)
// GL_ONE_MINUS_DST_ALPHA = 1- kênh alpha của đích (Dùng cho source or destination)
// GL_SRC_ALPHA_SATURATE = Min(Kênh Alpha của nguồn, 1- kênh alpha của đích) (Dùng cho source)
//Trông thì hơi ít nhưng kết hợp hết chúng lại+áp dụng đúng cách sẽ tạo ra cả đống hiệu ứng blending
GLBlendFunc(GL_ONE,GL_ONE);
//Vẽ đẹp chút xíu nha cha nội
GLHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
//Load một cái texture dùng chơi
LoadTexture('Demo.bmp',DemoTex);
Result:=True;
End;
PROCEDURE TNewBieEngine.BeginRender;
Begin
//Xoá buffer, cả Z-buffer lun
GLClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
//Trong OpenGL sử dụng một toạ độ gốc (giống như là toạ độ ở unit CRT trong Pascal thường zị
//hàm này dùng để reset toạ độ gốc đó về chuẩn (0,0,0)
GLLoadIdentity;
End;
PROCEDURE TNewBieEngine.EndRender;
Begin
//Chuyển buffer ra màn hình
SwapBuffers(HDCHandle);
End;
PROCEDURE TNewBieEngine.PeekMessages;
Var Msg : TMsg;
Begin
If PeekMessage(Msg,0,0,0,PM_REMOVE) then
Begin
If Msg.Message=WM_QUIT then Finished:=True
Else
Begin
TranslateMessage(Msg);
DispatchMessage(Msg);
End;
End;
End;
PROCEDURE TNewBieEngine.Process;
Begin
//Nhấn escape hả ? Iem quit.
If Keys[27] then Finished:=True;
End;
PROCEDURE TNewBieEngine.Drawing;
Begin
//Nhảy zề toạ độ (0,0,0)
GLLoadIdentity;
//Hàm GLColor3F để chỉnh màu mà bạn muốn chỉ đinh OpenGL vẽ ra,
//lưu ý là R,G,B là số thực nằm trong khoảng [0,1]. Nếu muốn đếm
//R,G,B bằng số nguyên trong khoảng [0,255] như bình thường thì
//có thể sử dụng hàm GLColor3UB
GLColor3F(1,1,1);
//Hàm translate kiểu tựa như GotoXY thui, nó di chuyển "con trỏ" đến một toạ độ mới
GLTranslate(-20,10,-50);
//Bắt đầu vẽ một tam giác, nguyên tắc vẽ của OpenGL thông thường là GLBegin(Kiểu muốn vẽ)
//và sau đó lần lượt là những thông số về đỉnh muốn vẽ, màu, tex coord (sẽ nói sau) của những
//đỉnh tương ứng, cuối cùng là GLEnd để kết thúc lệnh vẽ. Thông thường sử dụng thông dụng nhất
//là vẽ tam giác hoặc tứ giác (GL_TRIANGLES và GL_QUAD)
//Vẽ tam giác thì đương nhiên là cần 3 đỉnh, ở đây simple nhất là tui đẩy 3 đỉnh lần lượt vào
//bằng hàm GLVertex3F(Toạ độ đỉnh X,Y,Z).
//Giữa cặp GLBegin và GLEnd này có thể đẩy nhiều tam giác khác nhau
GLBegin(GL_TRIANGLES);
GLVertex3F( 0.0, 3.0, 0.0);
GLVertex3F(-3.0,-3.0, 0.0);
GLVertex3F( 3.0,-3.0, 0.0);
GLEnd;
//Ở đây dịch con trỏ sang phải một xíu, vẫn là vẽ tam giác nhưng bạn chú ý nhé, ở đó
//tôi viết hàm GLColor3F trước khi đẩy mỗi đỉnh vô >> đó chính là màu của mỗi đỉnh tam giác đó
//Bạn có thể théc méc: Oh, thế đỉnh tam giác có màu như zị, zị giữa tam giác thì vẽ màu gì ?
//Đơn giản thui, zĩ nhiên là phần ở giữa kô fải là tô đặc một màu rùi, mà nó được tô theo một
//phương pháp nhất định để giải màu biến chuyển tự nhiên giữa các đỉnh với nhau, phương pháp
//mà OpenGL dùng mặc định là Gouraud (híp, kô bít viết tên pác này có đúng kô, nếu sai thì sozzy nhớ)
//Bạn hãy thử đổi những chỉ số màu khác để theo dõi
GLTranslate(10,0,0);
GLBegin(GL_TRIANGLES);
GLColor3F(1.0,0.5,0.5);
GLVertex3F( 0.0, 3.0, 0.0);
GLColor3F(0.5,0.5,0.5);
GLVertex3F(-3.0,-3.0, 0.0);
GLColor3F(0.0,0.5,0.5);
GLVertex3F( 3.0,-3.0, 0.0);
GLEnd;
//Òe, zị iem thấy game nó vẽ có ảnh ẻo đàng hoàng mừ, có thằng lào chỉ tô màu kô mô ? Giống..mẫu giáo
//wá ? He he, đừng nóng, để tui nói tiếp về áp vật liệu, cái thằng texture mình khai báo chính là dùng
//ở đây đây. Đầu tiên là phải yêu cầu bind (nôm na là cầm nó lên dán vô í mờ), sau đấy cho phép OpenGL
//dùng thằng texture đấy để áp vô hình mình vẽ.
GLBindTexture(GL_TEXTURE_2D,DemoTex);
GLEnable(GL_TEXTURE_2D);
//Vẽ thử cái hén ?
//Ở đây có hàm mới là GLTexCoord2F ? Cái chi zị ? Nó là hàm chỉ định đỉnh đó thì kéo điểm ảnh nào vô để
//"dán" đó. Do một cái texture là 2D *(chữ nhật) nên mình chỉ cần chỉ định đỉnh cần kéo thôi.
GLColor3F(1,1,1);
GLTranslate(10,0,0);
GLBegin(GL_TRIANGLES);
GLTexCoord2F(0,0);
GLVertex3F( 0.0, 3.0, 0.0);
GLTexCoord2F(0,1);
GLVertex3F(-3.0,-3.0, 0.0);
GLTexCoord2F(1,0);
GLVertex3F( 3.0,-3.0, 0.0);
GLEnd;
//Tương tự cũng áp texture nhưng thay cả màu mè xem seo hén:
GLTranslate(10,0,0);
GLBegin(GL_TRIANGLES);
GLTexCoord2F(0,0);
GLColor3F(1.0,0.5,0.5);
GLVertex3F( 0.0, 3.0, 0.0);
GLTexCoord2F(0,1);
GLColor3F(0.5,0.5,0.5);
GLVertex3F(-3.0,-3.0, 0.0);
GLTexCoord2F(1,0);
GLColor3F(0.0,0.5,0.5);
GLVertex3F( 3.0,-3.0, 0.0);
GLEnd;
//Ở đây kô áp texture nữa nên bỏ nó đi
GLDisable(GL_TEXTURE_2D);
//Hè hè, lại quay lại toạ độ đầu.
GLLoadIdentity;
//Nhảy đi một chút, xuống dưới mí tam giác đã vẽ lúc nãy
GLTranslate(-20,0,-50);
//Vẽ một cái hình vuông, nếu thích bạn cứ thay đổi toạ độ thoải mái để xem nó kì quái ra sao
//Chú í, vẽ hình này thực ra là vẽ 2 tam giác với toạ độ lần lượt là [1,2,3] và [1,4,3] (Số ở
//đây là số hiệu của đỉnh đẩy vô đó).
GLBegin(GL_QUADS);
GLVertex3F(-3.0, 3.0, 0.0);
GLVertex3F( 3.0, 3.0, 0.0);
GLVertex3F( 3.0,-3.0, 0.0);
GLVertex3F(-3.0,-3.0, 0.0);
GLEnd;
//Vẽ một thằng màu mè linh tinh
GLTranslate(10,0,0);
GLBegin(GL_QUADS);
GLColor3F(0.0,0.5,0.5);
GLVertex3F(-3.0, 3.0, 0.0);
GLColor3F(1.0,0.8,0.5);
GLVertex3F( 3.0, 3.0, 0.0);
GLColor3F(0.0,0.9,0.1);
GLVertex3F( 3.0,-3.0, 0.0);
GLColor3F(1.0,0.5,0.8);
GLVertex3F(-3.0,-3.0, 0.0);
GLEnd;
//Lại thử áp texture xem seo ?
//Lệnh bind ở đây thực ra là thừa vì bên trên cũng bind thằng này rùi, OpenGL vẫn "ghi nhớ" nó
GLBindTexture(GL_TEXTURE_2D,DemoTex);
GLEnable(GL_TEXTURE_2D);
//Vẽ thử có texture
GLColor3F(1,1,1);
GLTranslate(10,0,0);
GLBegin(GL_QUADS);
GLTexCoord2F(0,1);
GLVertex3F(-3.0, 3.0, 0.0);
GLTexCoord2F(1,1);
GLVertex3F( 3.0, 3.0, 0.0);
GLTexCoord2F(1,0);
GLVertex3F( 3.0,-3.0, 0.0);
GLTexCoord2F(0,0);
GLVertex3F(-3.0,-3.0, 0.0);
GLEnd;
//Vẽ cả màu vào xem seo
GLTranslate(10,0,0);
GLBegin(GL_QUADS);
GLTexCoord2F(0,1);
GLColor3F(0.0,0.5,0.5);
GLVertex3F(-3.0, 3.0, 0.0);
GLTexCoord2F(1,1);
GLColor3F(1.0,0.8,0.5);
GLVertex3F( 3.0, 3.0, 0.0);
GLTexCoord2F(1,0);
GLColor3F(0.0,0.9,0.1);
GLVertex3F( 3.0,-3.0, 0.0);
GLTexCoord2F(0,0);
GLColor3F(1.0,0.5,0.8);
GLVertex3F(-3.0,-3.0, 0.0);
GLEnd;
//
GLDisable(GL_TEXTURE_2D);
//Hàm GLFlush này có tác dụng "ép" OpenGL vẽ tuốt những gì nó đang lưu
//vì có lúc OpenGL lưu trữ nhưng lệnh bạn "ra lệnh" vào buffer rồi tối ưu,
//sau đó mới vẽ một thể.
GLFlush;
End;
PROCEDURE TNewBieEngine.Running;
Begin
Repeat
PeekMessages;
Process;
BeginRender;
Drawing;
EndRender;
Until Finished;
End;
FUNCTION TNewBieEngine.CreateTexture(SizeW,SizeH,Format : Word;PData : Pointer) : Integer;
Var Texture : GLUInt;
Begin
//Tạo một em texture instance mới
GLGenTextures(1,Texture);
//Bind thằng này lại
GLBindTexture(GL_TEXTURE_2D,Texture);
//Cấu hình kiểu map, cái này sẽ nói rõ sau zì zờ tui cũng chưa nghĩ ra giải thích hợp lí
//Có thể nói đại loại đây là phương thức để raster data của mình thành một cái texture
//ví dụ như scale, smoothing...
GLTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MO DULATE);
GLTexParameterI(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,GL_LINEAR);
GLTexParameterI(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R,GL_LINEAR);
//Build một texture tuỳ theo format được chỉ định
If Format=GL_RGBA then
GLUBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,SizeW,Size H,GL_RGBA,GL_UNSIGNED_BYTE,PData)//32bit, có kênh alpha
Else GLUBuild2DMipmaps(GL_TEXTURE_2D,3,SizeW,SizeH,GL_R GB,GL_UNSIGNED_BYTE,PData);//24bit, kô có kênh alpha
Result:=Texture;
End;
FUNCTION TNewBieEngine.LoadTexture(FileName : String;Var Texture : GLUInt) : Boolean;
Var FileHeader : BitmapFileHeader;
InfoHeader : BitmapInfoHeader;
Palette : Array of RGBQuad;
BitmapFile : THandle;
BitmapLength,PaletteLength,ReadBytes : LongWord;
Front,Back : ^Byte;
Temp : Byte;
I,SizeW,SizeH : Integer;
PData : Pointer;
Begin
//Hàm này chỉ đọc một file BMP raw và create texture từ nó thôi, kô có giề đặc biệt cả
Result:=False;
BitmapFile:=CreateFile(PChar(FileName),GENERIC_REA D,
FILE_SHARE_READ,Nil,OPEN_EXISTING,0,0);
If BitmapFile=INVALID_HANDLE_VALUE then Exit;
ReadFile(BitmapFile,FileHeader,SizeOf(FileHeader), ReadBytes,Nil);
ReadFile(BitmapFile,InfoHeader,SizeOf(InfoHeader), ReadBytes,Nil);
PaletteLength:=InfoHeader.biClrUsed;
SetLength(Palette,PaletteLength);
ReadFile(BitmapFile,Palette,PaletteLength,ReadByte s,Nil);
If ReadBytes<>PaletteLength then Exit;
SizeW:=InfoHeader.BIWidth;
SizeH:=InfoHeader.BIHeight;
BitmapLength:=InfoHeader.BISizeImage;
If BitmapLength=0 then
BitmapLength:=SizeW*SizeH*InfoHeader.BIBitCount div 8;
GetMem(PData,BitmapLength);
ReadFile(BitmapFile,PData^,BitmapLength,ReadBytes, Nil);
If ReadBytes<>BitmapLength then Exit;
CloseHandle(BitmapFile);
For I:=0 to SizeW*SizeH-1 do
Begin
Front:=Pointer(Integer(PData)+I*3);
Back:=Pointer(Integer(PData)+I*3+2);
Temp:=Front^;
Front^:=Back^;
Back^:=Temp;
End;
Texture:=CreateTexture(SizeW,SizeH,GL_RGB,PData);
FreeMem(PData);
Result:=True;
End;
PROCEDURE TNewBieEngine.ReSizeWindow(SizeW,SizeH : Integer);
Begin
//Đặt viewport
GLViewport(0,0,SizeW,SizeH);
GLMatrixMode(GL_PROJECTION);
GLLoadIdentity;
//Ở đây OpenGL có 2 cách nhìn: Một là Othor (quan tâm sau) nó như là nhìn tất cả thẳng băng zị
//kô có thể hiện chiều sâu, chế độ này dùng để vẽ 2D hoặc select object là chính. Chế độ thứ 2 là perspective,
//chế độ này có định nghĩa góc nhìn (số 45 đó, dùng 90 thì thực hơn), tỉ lệ giữa Width và Height, Z min
//và Z max (Những Z vượt quá giới hạn này sẽ bị tiêu tùng, cóc nhìn được :>) Trong chế độ này hình ảnh ở xa hơn
//sẽ có những biến đổi theo nguyên tắc nhìn quang học
GLUPerspective(45.0,SizeW/SizeH,1.0,100);
GLMatrixMode(GL_MODELVIEW);
GLLoadIdentity;
End;
PROCEDURE TNewBieEngine.KillWindow;
Begin
//Trở về chế độ cũ ?
If FullScreen then
Begin
ChangeDisplaySettings(DevMode(Nil^),0);
ShowCursor(True);
End;
//Xoá sổ mí em handle
If Not WGLMakeCurrent(HDCHandle,0) then ;
If Not WGLDeleteContext(HRCHandle) then HRCHandle:=0;
If (HDCHandle>0) and
(ReleaseDC(HWindow,HDCHandle)=0) then HDCHandle:=0;
//Xóa xổ thằng chả window useless
If (HWindow<>0) and
(Not DestroyWindow(HWindow)) then HWindow:=0;
//Xoá sổ window class luôn
If Not UnRegisterClass(WindowClass,HInstance) then HInstance:=0;
End;
BEGIN
NewBieEngine:=TNewBieEngine.Create;
//Tạo một cửa sổ kích thước 1024x768, kô được thì iem quit (độ sâu màu 16 ở đây kô còn quan trọng vì nó
//dùng độ sâu màu chuẩn hiện tại). Nếu muốn fullscreen thì chỉnh thêm zô hén.
If Not NewBieEngine.Setup(1024,768,16,WindowNoButtons) then Halt;
//Chạy thử đê nào
NewBieEngine.Running;
NewBieEngine.Destroy;
END.
Good !
ma hinh nhu bac thich Pascal ha ?
tui nghe noi bac co 3D GS phai khong ? ban lai cho tui nhe .
Các bạn down load tutor này ở đây nhé http://genetic.vngate.net/diendan/mi...tachmentid=903. Chương trình viết bằng Delphi, dịch ngon với Delphi 7, 8 beta. Các phiên bản khác chưa thử. Có cả bản HTML của phần viết nhì nhằng trên nên các bạn kô cần phải save trang này lại đâu.
PS: Sozzy bạn gì post bài ở trên nhưng mà mình đã nói là kô chat chit ở đây. Phải move thui.
Ê , Cb ơi hôm nào làm một bài về stencil_Buffer đi em đang cần .
bác CB có biết người ta làm game cho PS2 bằng cái gì không, chắc là OpenGL hả, nhưng còn các công cụ khác thế nào. tui newbie, nhờ bác giúp. (À nữa, các bác đừng có khuyên nhủ tui cái chuyện mới học đã đòi làm game lớn, PS2 cơ đấy, tui nghe đủ nhưng lời khuyên như vậy rồi! tôi chỉ muốn hỏi, học và hỏi, thế thôi. cám ơn các bác
Thêm nữa! có ai hiểu rõ mấy cái ma trận của hai phép chiếu Ortho và Perpective thì giảng cho tui, ngảy xưa tui học phép chiếu nó không giống thế này, ai đó giải thích căn nghuyên từ đâu mà nó đẻ ra 2 cái ma trận kì diệu đó thì giúp tôi. :help:
Bác CB cho lại cái link đi, die mất rùi.
Sozzy các đồng chí dạo này zợ con đùm đúm wé hông làm được giề cả.
Link tui sẽ up lại sau.
PS2 dùng cơ chế đồ họa riêng, tham khảo PS2 Development Kit nhé.
Bookmarks