opengl最初是由シリコン图形公司开发的底层图形库规范。你的系统中准确实现这个规范的部分、通常被称为opengl驱动、它允许你使用几何集合(点、线、多边形、多边形、图像等等)来描述你希望表现的场景。让肉眼观察起来较为舒适的中等规模场景、通常在毫秒级的速度上实现、这意味着该库文件有足够的能力来支持你创建一个生机勃勃的虚拟世界。
opengl驱动一般以二进制库文件的形式提供。它能够动态的连接到你的程序中。在windows平台上、它将是成为dllopengl.dll使用任何dll开始、它对opengl 3d
数学基础
opengl拥有强大的数学基础、因此对它功能的限制完全取决于你的想象能力(译者注:没有做不到、只有想不到)。对于理解那些公理和引理、更好的是让我们立刻认识一个简单的3D坐标系统、它是3D编程中惯用的坐标系统。如下:
你应该如何理解你的屏幕(蓝色的方块)在场景中的放置位置呢?发出四条射线并形成屏幕的那个点、是该想象空间中的视点(視点)。pengl让你调用两个简单的函数来定义这个场景
glmatrixmode(gl_projection);
Glfrustum(-0.1、0.1、-0.1、0.1、0.3、25.0);
在这个调用的过程中的-0.1,0.1、-0.1,0.1 )同时25.0指定「远剪贴板」(遠い切り抜き平面)。任何近剪贴板前面的物体以及远剪贴板后面的物体都将不可见。当然、你能够任意摆弄这些数字、以使他们适合你需要的场景。
从基本元素(原始)到对象
现在开始最有意思的部分:对象。opengl仅仅支持以下几种基本几何图形:点、线和多边形。没有表面或者更高级的图形(比如球状图形)能被作为基本图形元素绘制。但是它们能够用多边形完美的模仿出来。随意看看现代3D游戏、你会发现它们完全由三角形建立。因此、我们不会被此限制所约束。
对象的绘制非常类似パスカル语言编程。每个块都应该被begined包含着、更为确切的说是glbegin()和glend()。如同下面的例子:。如同下面的例子:
const s = 1.0; d = 5.0;
...
glbegin(gl_triangles);
glvertex3f(-s、0、d); glvertex3f(s、0、d); glvertex3f(0、s、d);
グレンド;
这是个简单的三角形。它距离你的视点有5个单位、自身高1个单位、宽2
这是屏幕截图:
即使它看起来不象3D图形、但它是我们的初始块。在下面你可以看到这个例子的源代码。
在你开始钻研代码前、还有些话要说。每次opengl编程、都包含一些初始化输出设备的os设定(OS固有)代码。如果你使用win32、你将需要设置像素格式以及建立显示上下文环境脱离windows设备上下文环境。如果windows、你可以把如下的代码作为模版使用。formcreate
ファイル:tri.pas
ユニットトライ;
インタフェース
用途
OpenGL、Windows、メッセージ、sysutils、クラス、グラフィック、コントロール、フォーム、ダイアログ、
stdctrls、extctrls、comctrls;
タイプ
tform1 = class(tform)
手順formcreate(sender:tobject);
手順フォームペイント(送信者:tobject);
プライベート
手順の描画; //リクエストに応じてOpenGLシーンを描画します
公共
終わり;
var
form1:tform1;
実装
{$ r *.dfm}
手順Setuppixelformat(DC:HDC);
const
PFD:tpixelformatdescriptor =(
nsize:sizeof(tpixelformatdescriptor); // サイズ
nversion:1; //バージョン
dwflags:pfd_support_openglまたはpfd_draw_to_windowまたは
pfd_doublebuffer; //ダブルバッファリングをサポートします
iPixelType:pfd_type_rgba; //カラータイプ
ccolorbits:24; //優先色の深さ
クレジット: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; //メインレイヤー
保存状態:0;
dwlayermask:0;
dwvisiblemask:0;
dwdamagemask:0; //レイヤー、可視、損傷マスクはありません
);
var pixelformat:整数;
始める
pixelformat:= choosepixelformat(dc、@pfd);
if(pixelformat = 0)then
出口;
if(setpixelformat(dc、pixelformat、@pfd)<> true)then
出口;
終わり;
手順グリニット;
始める
//表示される予測を設定します
glmatrixmode(gl_projection);
Glfrustum(-0.1、0.1、-0.1、0.1、0.3、25.0);
//視聴者を位置付けます
glmatrixmode(gl_modelview);
Glenable(gl_depth_test);
終わり;
手順tform1.formcreate(sender:tobject);
var DC:HDC;
RC:HGLRC;
I:整数;
始める
DC:= getDC(ハンドル); //実際、ここでは任意のウィンドウコントロールを使用できます
setuppixelformat(dc);
rc:= wglcreateContext(dc); // DCからOpenGLウィンドウを作成します
wglmakecurrent(dc、rc); // OpenGLウィンドウをアクティブにします
グリニット; // openglを初期化します
終わり;
手順tform1.draw;
const s = 1.0; d = 5.0;
始める
glclear(gl_color_buffer_bitまたは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);
グレンド;
swapbuffers(wglgetcurrentdc);
終わり;
手順tform1.formpaint(sender:tobject);
始める
描く;
終わり;
終わり。
ファイル:tri.dfm
オブジェクトフォーム1:tform1
BORDERSTYLE = BSDIALOG
キャプション= '基本的なOpenGLプログラム'
ClientHeight = 318
clientWidth = 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 // vertexes
a1:tglarrayf3 =( - d、0、-h1); // bootom左
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);
glloadidentity;
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);
グレンド;
swapbuffers(wglgetcurrentdc);
終わり;
虽然看起来有点复杂、不过当你面对下面这张图时、它就很容易理解了。
我们定义顶点a1 - a4同时依据4个顶点位置建立指定的三角形。当你定义自己的三角形(或者其他的多边形)、请使用如下的规则:始终按照逆时针顺序排列定点序号、就像你正在外部观看侧面一样。通过这个规则、我们可以指定指定a1-a2-a4、a1-a3-a2(仰视)、a2-a3-a4和a3-a1-a4。
现在就替换tri.pas
ライト!カメラ! 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_projection);
Glfrustum(-0.1、0.1、-0.1、0.1、0.3、25.0);
// [視聴者の位置 */
glmatrixmode(gl_modelview);
Glenable(gl_depth_test);
//ライトを設定します
Glenable(gl_lighting);
gllightfv(gl_light0、gl_position、 @light0_position);
gllightfv(gl_light0、gl_ambient、@ambient);
Glenable(gl_light0);
終わり;
代码内的两个常量是必须的。一个定义光源位置(位于视点的后面的左上角)、另外一个定义环境光线。这将产生少量的散乱光线、使你能够看到完全位于阴影中的某些物体。
虽然你可以使用光照设定光源、可是物体仍然没有绘制阴影。这是因为opengl需要知道你指定的每个多边形的「通常」(通常の是一个与表面正交的向量)。如果你没有自己的向量函数库、可以使用以下方法计算三角形中三个顶点的、通常の。这个函数是以定点逆时针排列为基础的、因为通常の是一个向量的叉积、如果你不遵守该规则、会使向量指向四面体内部。
関数getnormal(p1、p2、p3:tglarrayf3):tglarrayf3;
var a、b:tglarrayf3;
始める
// 2つのベクトルを作成します
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];
//クロスプロダクトを計算します
result [0]:= a [1]*b [2] -a [2]*b [1];
result [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 // 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; //通常
始める
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);
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); glvertex3fv(@a4);
glnormal3fv(@n3);
glvertex3fv(@a2); glvertex3fv(@a3); glvertex3fv(@a4);
glnormal3fv(@n4);
glvertex3fv(@a3); glvertex3fv(@a1); glvertex3fv(@a4);
グレンド;
swapbuffers(wglgetcurrentdc);
終わり;
这便是以上代码的效果:
现在、使用一点、delphi Vcl提供的的东西。在窗体上放一个タイマー、指定一个类成员「角度:シングル」并在每次タイマー1:
手順tform1.timer1timer(sender:tobject);
始める
角度:=角度+1.0;
描く;
終わり;
opengl仅差条线:
glrotatef(角度、0.0、1.0、0.0);
把它放在glbegin()内三角开始绘制前的位置上、这样你的阴影部分就可以旋转了、至此、一切结束。