OpenGl silicon圖形公司開發的底層圖形庫規範。你的系統中準確實現這個規範的部分,通常被稱為opengl驅動,它允許你使用幾何集合(點,線,多邊形,圖像等等)來描述你希望表現的場景。讓肉眼觀察起來較為舒適的中等規模場景,通常在毫秒級的速度上實現,這意味著該庫文件有足夠的能力來支持你創建一個生機勃勃的虛擬世界。,這意味著該庫文件有足夠的能力來支持你創建一個生機勃勃的虛擬世界。
OpenGl windows平台上,它將是成為dll 的形式(在你的系統目錄下檢查 opengl.dll)。自從delphi能夠使用任何dll開始
數學基礎
opengl擁有強大的數學基礎,因此對它功能的限製完全取決於你的想像能力:譯者註:沒有做不到,只有想不到),更好的是讓我們立刻認識,更好的是讓我們立刻認識一個簡單的3d坐標系統,它是3d::
你應該如何理解你的屏幕(藍色的方塊)在場景中的放置位置呢?發出四條射線並形成屏幕的那個點,是該想像空間中的視點(觀點)。opengl簡單的函數來定義這個場景
glmatrixmode(gl_provoction);
glfrustum(-0.1,0.1,-0.1,0.1,0.3,25.0);
在這個調用的過程中的-0.1,0.1,-0.1,0.1 定義了這個可視屏幕的左上角和右下角坐標; 0.3指定視點到屏幕的距離(就好像“近剪貼板”(靠近剪裁平面)同時25.0指定“遠剪貼板”(遠剪平平面)。任何近剪貼板前面的物體以及遠剪貼板後面的物體都將不可見。當然,你能夠任意擺弄這些數字,以使他們適合你需要的場景。
從基本元素(原始)到對象
現在開始最有意思的部分:對象。opengl:點:線和多邊形。沒有表面或者更高級的圖形,線和多邊形。沒有表面或者更高級的圖形(比如球狀圖形)能被作為基本圖形元素繪製。但是它們能夠用多邊形完美的模仿出來。隨意看看現代3d遊戲,你會發現它們完全由三角形建立。因此,我們不會被此限制所約束。,我們不會被此限制所約束。
對象的繪製非常類似pascal語言編程。每個塊都應該被開始 - end
const s = 1.0; d = 5.0;
...
glbegin(gl_triangles);
glvertex3f(-s,0,d); glvertex3f(s,0,d); glvertex3f(0,s,d);
glend;
這是個簡單的三角形。它距離你的視點有5個單位,自身高,1個單位,寬2個單位。
這是屏幕截圖:
即使它看起來不像3d圖形,但它是我們的初始塊。在下面你可以看到這個例子的源代碼。
在你開始鑽研代碼前,還有些話要說。每次,opengl編程,都包含一些初始化輸出設備的os設定(特定於OS)代碼。如果你使用win32,你將需要設置像素格式以及建立顯示上下文Windows設備上下文環境。如果Windows系統級編程你並不很在行,FormCreate中被調用函數的詳細信息可以參考幫助文檔。
文件:tri.pas
單位TRI;
介面
用途
OpenGL,Windows,Messages,Sysutils,類,圖形,控件,表單,對話框,
stdctrls,extctrls,comctrls;
類型
tform1 = class(tform)
過程FormCreate(發送者:tobject);
過程FormPaint(發送者:tobject);
私人的
過程抽獎; //根據要求繪製OpenGL場景
民眾
結尾;
var
form1:tform1;
執行
{$ r *.dfm}
過程setupixelformat(DC:HDC);
const
pfd:tpixelformatDescriptor =(
nsize:sizeof(tpixelformatDescriptor); // 尺寸
nversion:1; // 版本
dwflags:pfd_support_opengl或pfd_draw_to_to_window或
pfd_doublebuffer; //支持雙重緩衝
ipixeltype:pfd_type_rgba; //顏色類型
Ccolorbits:24; //首選的顏色深度
CredBits:0;信用班: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; //主層
大號:0;
dwlayermask:0;
dwvisiblembask:0;
dwdamagemask:0; //沒有圖層,可見,傷害口罩
);
var pixelformat:整數;
開始
pixelformat:= peacepixelformat(dc,@pfd);
如果(pixelformat = 0),則
出口;
if(setPixelforMat(DC,PixelforMat,@pfd)<> true)然後
出口;
結尾;
程序查看;
開始
//設置觀看投影
glmatrixmode(gl_provoction);
glfrustum(-0.1,0.1,-0.1,0.1,0.3,25.0);
//位置查看器
glmatrixmode(gl_modelview);
glenable(gl_depth_test);
結尾;
過程tform1.formCreate(發件人:tobject);
VAR DC:HDC;
RC:HGLRC;
我:整數;
開始
DC:= getDC(handle); //實際上,您可以在此處使用任何窗口的控件
SetUppixelFormat(DC);
RC:= WGLCreateContext(DC); //使openGL窗口從DC中脫出
WGLMAKECURRENT(DC,RC); //使OpenGL窗口活動活動
光明; //初始化OpenGL
結尾;
過程tform1.draw;
const s = 1.0; d = 5.0;
開始
glclear(gl_color_buffer_bit或gl_depth_buffer_bit);
GLLODIDDICTITY;
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);
結尾;
過程tform1.formpaint(發件人:tobject);
開始
畫;
結尾;
結尾。
文件:tri.dfm
對象形式1:tform1
borderstyle = bsdialog
字幕='Basic OpenGL程序'
客戶端= 318
客戶端= 373
onCreate = formCreate
OnPaint = FormPaint
結尾
3d歷險
好了,讓我們開始真正的,3d吧。將先前的代碼作為框架,我們增加一些畫線的代碼建立一個帶陰影面的四面體。應該如何用基本圖形元素來構建呢?我們使用四個三角形。,我們增加一些畫線的代碼建立一個帶陰影面的四面體。應該如何用基本圖形元素來構建呢?我們使用四個三角形。一個在底部,另外三個作為側面。這裡就是生成他們的代碼::
過程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 //頂點
a1:tglarrayf3 =(-d,0,-h1); //向左引導
a2:tglarrayf3 =(d,0,-h1); // bootom正確
a3:tglarrayf3 =(0,0,h2); // BOOTOM返回
a4:tglarrayf3 =(0,hy,0); //頂部
開始
glclear(gl_color_buffer_bit或gl_depth_buffer_bit);
GLLODIDDICTITY;
gltranslatef(0.0,0.0,-12.0);
glbegin(gl_triangles);
glvertex3fv(@a1); glvertex3fv(@a3); glvertex3fv(@a2);
glvertex3fv(@a1); glvertex3fv(@a2); glvertex3fv(@a4);
glvertex3fv(@a2); glvertex3fv(@a3); glvertex3fv(@a4);
glvertex3fv(@a3); glvertex3fv(@a1); glvertex3fv(@a4);
glend;
SwapBuffers(wglgetCurrentDC);
結尾;
雖然看起來有點複雜,不過當你面對下面這張圖時,它就很容易理解了。,它就很容易理解了。
我們定義頂點A1 - a4同時依據4個頂點位置建立指定的三角形。當你定義自己的三角形(或者其他的多邊形),請使用如下的規則:始終按照逆時針順序排列定點序號,就像你正在外部觀看側面一樣。通過這個規則,A1-A2-A4,A1-A3-A2,A2-A3-A4和A3-A1-A1-A4。
現在就替換tri.pas中tform1.darw()部分,程序運行的效果不會體現出過多的變化。它看起來仍然不像三維圖形。這是因為我們還沒有設定任何光源。,程序運行的效果不會體現出過多的變化。它看起來仍然不像三維圖形。這是因為我們還沒有設定任何光源。
燈!相機! OpenGL!
在opengl:光源自身(顏色:光源自身(顏色,強度等等),依次包括顏色,依次包括顏色,一些物理參數(比如不透明性光澤性)以及紋理。深入其中世界,我們將一步步地接近。 ,我們將一步步地接近。
定義一個光源相當容易。
程序查看;
const
light0_position:tglarrayf4 =(-8.0,8.0,-16.0,0.0);
環境:tglarrayf4 =(0.3,0.3,0.3,0.3);
開始
//設置觀看投影
glmatrixmode(gl_provoction);
glfrustum(-0.1,0.1,-0.1,0.1,0.3,25.0);
//位置查看器 */
glmatrixmode(gl_modelview);
glenable(gl_depth_test);
//設置燈
可亮(gl_lighting);
gllightfv(gl_light0,gl_position, @light0_position);
gllightfv(gl_light0,gl_ambient, @ambient);
可亮(gl_light0);
結尾;
代碼內的兩個常量是必須的。一個定義光源位置(位於視點的後面的左上角),另外一個定義環境光線。這將產生少量的散亂光線,使你能夠看到完全位於陰影中的某些物體。
雖然你可以使用光照設定光源,可是物體仍然沒有繪製陰影。這是因為opengl需要知道你指定的每個多邊形的“正常”以便進行光線計算(正常是一個與表面正交的向量)。如果你沒有自己的向量函數庫,正常。這個函數是以定點逆時針排列為基礎的,因為正常是一個向量的叉積,如果你不遵守該規則,會使,會使向量指向四面體內部。
函數getnormal(p1,p2,p3:tglarrayf3):tglarrayf3;
var a,b:tglarrayf3;
開始
//做兩個向量
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];
//計算交叉產品
結果[0]:= A [1]*B [2] -a [2]*B [1];
結果[1]:= A [2]*B [0] -a [0]*B [2];
結果[2]:= A [0]*B [1] -a [1]*B [0];
結尾;
使用這個函數,就可以設定所有的計算光線必需的信息了::
過程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 //頂點
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; //正常
開始
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或gl_depth_buffer_bit);
可亮(gl_normize);
glshademodel(gl_flat);
glcullface(gl_back);
GLLODIDDICTITY;
gltranslatef(0.0,0.0,-12.0);
glbegin(gl_triangles);
glnormal3fv(@n1);
glvertex3fv(@a1); glvertex3fv(@a2); glvertex3fv(@a3);
glnormal3fv(@n2);
glvertex3fv(@a1); glvertex3fv(@a2); glvertex3fv(@a4);
glnormal3fv(@n3);
glvertex3fv(@a2); glvertex3fv(@a3); glvertex3fv(@a4);
glnormal3fv(@n4);
glvertex3fv(@a3); glvertex3fv(@a1); glvertex3fv(@a4);
glend;
SwapBuffers(wglgetCurrentDC);
結尾;
這便是以上代碼的效果:
現在,使用一點delphi vcl提供的的東西。在窗體上放一個計時器,指定一個類成員“角度:單”並在每次計時器觸發時讓他增加1:
過程tform1.timer1timer(發件人:tobject);
開始
角度:=角度+1.0;
畫;
結尾;
離一個充滿生氣的opengl僅差條線:
glrotatef(角度為0.0,1.0,0.0);
把它放在glbegin()內三角開始繪製前的位置上,這樣你的陰影部分就可以旋轉了,至此,一切結束。,一切結束。