Итак, я начну сдесь рассказ о Д3Д. Этот документ создается мной в процессе обучения. Поэтому я не гарантирую правильность информации. Для начала работы с Д3Д вам нужен маломальски путний хидер или группа хидеров по Д3Д. Я выставлю сдесь одну такую группу которую создала группа JEDI. Для начала подключите себе в USES такие модули: ddraw,d3d,d3dtypes,d3dcaps, d3dmatch; Затем, вам понадобится описать все нужные объекты: dd:IDirectDraw; {необходим как базовый объект} d3d_:IDirect3D2; {собственно d3d и есть} d3dd:IDirect3DDevice2; {объект, который рендерит} p_s,dds:IDirectDrawSurface; {поверхности, первичная и для рендеринга} vp:IDirect3dViewPort2; {ВьевПорт, область экрана, в которую происходит рендеринг} w,v,p:TD3DMatrix; {матрицы - мира, камеры и проекции на экран} Затем следует процедура инициализации объектов. Когда будете делать это сами, контролируйте ошибки. procedure initialize; var ddsd:TDDSurfaceDesc; search:TD3DFINDDEVICESEARCH ; res:TD3DFINDDEVICERESULT ; viewport:TD3DVIEWPORT ; begin s_width:=640; s_height:=480; if directdrawcreate(nil,dd,nil)=dd_ok then; if dd.SetCooperativeLevel(handle,ddscl_exclusive or ddscl_fullscreen)=dd_ok then; if dd.SetDisplayMode(s_width,s_height,16)=dd_ok then; {обязательно 16битовый режим для софтыарного драйвера} fillchar(ddsd,sizeof(ddsd),0); with ddsd do begin dwSize:=sizeof(ddsd); dwFlags:=ddsd_caps; ddscaps.dwCaps:=DDSCAPS_primarysurface; end; if dd.createsurface(ddsd, p_s,nil)<>dd_ok then ; fillchar(ddsd,sizeof(ddsd),0); with ddsd do begin dwSize:=sizeof(ddsd); dwFlags:=ddsd_caps or ddsd_width or ddsd_height; dwWidth:=s_width; dwHeight:=s_height; ddscaps.dwCaps:=ddscaps_3ddevice or DDSCAPS_offscreenplain or ddscaps_systemmemory; end; if dd.createsurface(ddsd, dds,nil)<>dd_ok then ; if dd.QueryInterface(iid_idirect3d2,d3d_)<>dd_ok then; {создается d3d} ZeroMemory(@search, sizeof(search)); search.dwSize:= sizeof(search); search.dwFlags:= D3DFDS_HARDWARE; search.bHardware:= false; ZeroMemory(@res, sizeof(res)); res.dwSize:= sizeof(res); if D3D_.FindDevice(search,res)<>DD_OK then ; if d3d_.CreateDevice(res.guid{},dds,d3dd)<>dd_ok then; ZeroMemory(@viewport, sizeof(viewport)); viewport.dwSize:= sizeof(viewport); viewport.dwWidth:= s_width; viewport.dwHeight:= s_height; viewport.dvMaxZ:= 1000.0; viewport.dvMinZ:=0; viewport.dvScaleX:= s_width / 4.0; viewport.dvScaleY:= s_height / 4.0; viewport.dvMaxX:= D3DVAL(2.0); viewport.dvMaxY:= D3DVAL(2.0);{} if d3d_.CreateViewport(vp,nil)<>dd_ok then {beep}; if d3dd.AddViewport(vp)<>dd_ok then {beep}; if vp.SetViewport(viewport)<>dd_ok then {beep}; if d3dd.SetCurrentViewport(vp)<>dd_ok then {beep}; w:=identitymatrix; v:=ViewMatrix(D3DVECTOR(0,0,0), D3DVECTOR(0,0,1), D3DVECTOR(0,1,0), 0); p:=ProjectionMatrix(1, 1000.0, (60*PI/180));{угол обзора} if d3dd.SetTransform(D3DTRANSFORMSTATE_WORLD, W)<>dd_ok then {beep}; if d3dd.SetTransform(D3DTRANSFORMSTATE_VIEW,V)<>dd_ok then {beep}; if d3dd.SetTransform(D3DTRANSFORMSTATE_PROJECTION,P)<>dd_ok then {beep};{} end; Итак, что происходит в этой процедуре. Первым шагом создается ДиректДрав. Он создает первичную поверхность, и вторичную, трехмерную, поверхность. Далее он создает D3D, который в свою очередь ищщет подходящщий драйвер, и создает устройство рендеринга с этим драйвером. Далее создается вьевпорт, в котором устанавливаются необходимые значения, он присоединяется к устройству и делается текущщим. Потом устанавливаются параметры рендеринга для устройства. В инициализации все. Объекты созданны. Перед закрытием окна, не забудте удалить вьевпорт: if assigned(vp) then vp._Release; Что касается удаления - тот модуль, которым я пользовался раньше, не удалял объекты сам. Это делал я, с помощью метода release стандартного для всех COM объектов. Однако в тех хидерах, кои я использую сейчас, все иначе. Объекты убивает сам процесс при завершении. И если вы убъете их сами, то получится ошибка Access Violation At Addres Я подозреваю, что это связано с именем версии СОМ объекта раньше был 2 а теперь 3. Давайте теперь создадим текстуру. Ну, что такое текстура? Это картинка которая будет тображатся на вашем треугольнике. В Д3Д тектура хранится на поверхности, созданной с флагом DDSCAPS_texture. Итак, процедура function createtexture:boolean; var b:TBitMap; c:TCanvas; ddsd:DDSurfaceDesc; dc:Integer; begin result:=false; if not fileexists('file.bmp') then exit; b:=TBitMap.create; b.LoadFromFile('file.bmp'); fillchar(ddsd,sizeof(ddsd),0); with ddsd do begin dwSize:=sizeof(ddsd); dwFlags:=ddsd_caps or ddsd_width or ddsd_height; dwWidth:=b.Width; dwHeight:=b.height; ddscaps.dwCaps:=DDSCAPS_texture or ddscaps_systemmemory; end; if dd.createsurface(ddsd, tsurf,nil)<>dd_ok then exit; tsurf.getdc(dc); c:=TCanvas.create; c.handle:=dc; try c.Draw(0,0,b); finally c.free; b.free; tsurf.releasedc(dc); end; if tsurf.QueryInterface(iid_idirect3dtexture2,tex)<>dd_ok then exit; if tex.GetHandle(d3dd,htex)<>dd_ok then exit;{} result:=true; end; Перед этим вы должны описать такие переменные как tsurf:IDirectDrawSurface; tex:IDirect3DTexture2; hTex:TD3DTextureHandle; Что в ней происходит: сначала создается стандартный дельфевский TBitMap. Он нужен чтобы загрузить картинку с диска. Затем эта картинка загружается, и создается поверхность по размерам совпадающая с картинкой. Затем создается канвас, связывается с поверхностью, с его помощью на поверхность копируется изображение текстуры, и канвас убивается. Следующим шагом, поверхность создает собсно объект текстуры, а та в свою очередь создает Хэндл на текстуру, которую уже и можно применять при рендеринге. procedure render; procedure serv; var bfx:TDDBltFX; dr,sr:TRect; t:TSystemTime; begin zeromemory(@bfx,sizeof(bfx)); bfx.dwSize:=sizeof(bfx); dr.Left:=0; dr.Top:=0; dr.Right:=s_width; dr.Bottom:=s_height; sr.Left:=0; sr.Right:=s_width; sr.Top:=0; sr.Bottom:=s_height; if p_s.blt(@dr,dds,@sr,DDBLT_WAIT,bfx)<>dd_ok then {beep}; zeromemory(@bfx,sizeof(bfx)); bfx.dwSize:=sizeof(bfx); dds.Blt(NiL,NiL,NiL,DDBLT_WAIT or DDBLT_COLORFILL,bfx);{} end; var rr:TD3DRect; vv:array[0..2]of tD3DlVERTEX; begin vv[0]:=d3dlvertex(-1,1,3,clRed,0,0,1); vv[1]:=d3dlvertex(1,1,3,clGreen,0,1,0); vv[2]:=d3dlvertex(0,-1,3,clBlue,0,1,1); rr.x1:= 0; rr.y1:= 0; rr.x2:= S_WIDTH; rr.y2:= S_HEIGHT; vp.Clear(1, rr, D3DCLEAR_target); if d3dd.SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE,htex)<>d3d_ok then {beep}; if d3dd.BeginScene<>dd_ok then {beep}; if d3dd.DrawPrimitive(D3DPT_trianglelist,D3DVT_LVERTEX,@vv[0],3,0)<>dd_ok then {beep}; if d3dd.EndScene<>dd_ok then {beep}; serv; end; Эта процедура отображает один кадр. Вы можете вызывать ее из ОнТимера например. Что она делает: Вообще, целью этого текста является научить вас рисовать один треугольник на экране. Поняв как это делается, вы наверняка сможете сделать свои программы, строя объекты из треугольников. Итак - В этой процедуре есть процедура Serv которая предназначена для того чтобы скопировать изображение со вторичной поверхности на первичную. Сделав это она также очищает вторичную поверхность. В самой же процедуре Render происхдит следующее: сначала задаются все точки будущего треугольника d3dlvertex(x,y,z,color,specular,tX,tY) ну про x,y,z и color все понятно :-). Specular - цвет блестяших участков поверхности, он может отличаться от цвета матового. Пример - весь шар имеет цвет матовый, а то место, где в нем ярко отражается источник света имеет цвет Specular. Различаются по углу отражения лучей. Ставлю его в 0. а tX,tY это координаты точки на текстуре. Затем очищаем вьевпорт, vp.Clear. Затем указывем, какую текстуру мы хотим видеть: SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE,htex) и собственно отображаем треугольник с помощью DrawPrimitive. Как вы можете заметить, туда передается указатель на массив типа tD3DlVERTEX который характеризует точки, описывающие фигуру. Причем метод DrawPrimitive вы обязательно должны заключать в пару BeginScene EndScene На этом пока все. Разбираюсь с источником света.


Ну и ссылка домой. домой