- Ìíîãîñëîéíîå GL-òåêñòóðèðîâàíèå -
Ìíîãîñëîéíîå GL-òåêñòóðèðîâàíèå
Ìíå íà ãëàçà ïîïàäàëîñü íå ìàëî ñòàòåé íà òåìó OpenGL äëÿ Delphi, â êîòîðûõ ñíîâà è ñíîâà ðàçæ¸âûâàëèñü îñíîâû ïðîãðàììèðîâàíèÿ 3D-ãðàôèêè íà îñíîâå èñïîëüçîâàíèÿ áèáëèîòåêè OpenGL. Ñíîâà è ñíîâà ìåíÿ ó÷èëè ñîçäàâàòü óæå äî òîøíîòû çíàêîìûå GL-îêíà, ðèñîâàòü íà íèõ GL-ïðèìèòèâû è îãðàíè÷èâàëèñü ýòèì. Èíîãäà ìíå âåçëî, è ÿ ìîã ïðî÷åñòü â ñòàòüå î òîì, êàê íàòÿíóòü îäíó òåêñòóðó íà ïîâåðõíîñòü. Íî è â ýòîì ñëó÷àå àâòîð ñòàòüè íå óòðóæäàë ñåáÿ ðàçúÿñíåíèÿìè î òîì, êàê ìîæíî ñìåñòèòü òåêñòóðó ïî ïîâåðõíîñòè èëè ìàñøòàáèðîâàòü å¸ â ïðîèçâîëüíîì ìàñøòàáå, à íå ïðîñòî ïîâòîðÿòü å¸ ñòàíäàðòíûìè ñðåäñòâàìè. Òåì áîëåå, íèãäå ÿ íå ìîã ïðî÷åñòü, êàê âñ¸-òàêè ïðèìåíèòü ýòîò ïðåñëîâóòûé è ëåãåíäàðíûé Bump-mapping. À ìåæäó òåì, åù¸ ãäå-òî òàèëèñü ñåêðåòû íàëîæåíèÿ íåñêîëüêèõ òåêñòóð íà îäíó ïîâåðõíîñòü, ïðè óñëîâèè, ÷òî êîíâåéåð èìåþùåãîñÿ âèäåî àêñåëåðàòîðà ïîçâîëÿåò äåëàòü ýòî.
Òîãäà, íàó÷èâøèñü âñåìó ýòîìó ñàìîñòîÿòåëüíî, ÿ ðåøèë ñàì íàïèñàòü ñòàòüþ. Ñåâ çà íàïèñàíèå ñòàòüè, ÿ ðåøèë îïóñòèòü âñå ïîäðîáíîñòè ñîçäàíèÿ âñÿêèõ òàì îêîí, êîíòåêñòîâ óñòðîéñòâ è ïðî÷èõ àòðèáóòîâ, íåîáõîäèìûõ äëÿ òîãî, ÷òîáû âñÿ ýòà øòóêîâèíà çàâåðòåëàñü ó ÷èòàòåëÿ íà ýêðàíå ìîíèòîðà. Ñëåäîâàòåëüíî, ÿ áóäó îðèåíòèðîâàòüñÿ óæå íà îïûòíîãî ïðîãðàììèñòà, êîòîðûé óìååò äåëàòü âñå ýòè ïðèãîòîâëåíèÿ.
Êàêîå ó ìåíÿ ïîëó÷èëîñü äëèííîå âñòóïëåíèå. Âåðîÿòíî, ó êîãî-òî èç âàñ óæå ðóêè ÷åøóòñÿ îïðîáîâàòü âñ¸ ýòî íà ïðàêòèêå. Òîãäà ïðèñòóïèì. Ñíà÷àëà ñëåäóåò ïðèâåñòè õîòÿ áû ïðèáëèçèòåëüíîå îáúÿâëåíèå êëàññà òåêñòóðû
type TGLTexture = class
TexRepeatS, TexRepeatT : TGLTexRepeat;
TexSmooth : boolean;
TexEnvMode, Textured, TexID : GLint;
TexWidthScale, TexHeightScale, TexWidthOffset, TexHeightOffset : GLFloat;
procedure Init;
procedure BindTexture;
end;
Òîãäà ìåòîä èíèöèàëèçàöèè êëàññà äîëæåí áûòü òàêèì
procedure TGLTexture.Init;
begin
// Íàñòðîéêè ïî óìîë÷àíèþ
TexWidthScale := 1;
TexHeightScale := 1;
TexWidthOffset := 0;
TexHeightOffset := 0;
TexRepeatS := repRepeat;
TexRepeatT := repRepeat;
TexEnvMode := 1;
TexSmooth := true;
Textured := texNone;
TexID := -1; // òåêñòóðà åù¸ íå çàãðóæåíà
end;
Èç ìåòîäà ðèñîâàíèÿ ïîâåðõíîñòè äëÿ àêòèâàöèè òåêñòóðû ñëåäóåò âûçûâàòü ìåòîä BindTexture ýêçåìïëÿðà å¸ êëàññà. Èòàê, ðàññìîòðèì êîä ìåòîäà BindTexture è ïàðàëëåëüíî îáîñíóåì íåîáõîäèìîñòü ïàðàìåòðîâ òåêñòóðû.
Áåç ïàðàìåòðà TexID, ãäå äîëæåí õðàíèòüñÿ èíäåêñ çàðåãèñòðèðîâàííîé òåêñòóðû â GL-êîíòåêñòå, âîîáùå íèêóäà. Ýòî òîò ñàìûé èíäåêñ, óêàçàííûé â âûçîâå êîìàíäû glBindTexture ïðè çàãðóçêå òåêñòóðû ïðè ïîìîùè êîìàíäû glTexImage2D èëè gluBuild2DMipmaps. Ïðè ýòîì TexID äîëæåí ñîäåðæàòü íîìåð áîëüøå íóëÿ, ïîñêîëüêó 0 çàðåçåðâèðîâàí äëÿ ñòàðûõ âåðñèé, êîãäà áûëà âîçìîæíà òîëüêî îäíà òåêñòóðà.
procedure TGLTexture. BindTexture;
var Tmp, aTexRepS, aTexRepT, aTexSmooth, aTexModulate : GLint;
begin
if (Textured>texNone) and (TexID>0) then begin
// Àêòèâèçèðóåì 2D-òåêñòóðó
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexID);
Ïîñêîëüêó ìíå áû õîòåëîñü, ÷òîáû íà ïîâåðõíîñòü íàêëàäûâàëèñü íåñêîëüêî òåêñòóð, òî äîëæåí áûòü ñïèñîê òåêñòóð äëÿ êàæäîé ïîâåðõíîñòè. À ïîìèìî ýòîãî ëþáóþ òåêñòóðó ìîæíî âêëþ÷èòü èëè èñêëþ÷èòü èç íàëîæåíèÿ â êàêîé-òî ìîìåíò, íå óäàëÿÿ èç ñïèñêà òåêñòóð äëÿ äàííîé ïîâåðõíîñòè. Íî ãëóïî òàê ïðîñòî ðàñõîäîâàòü ïàìÿòü äëÿ ïàðàìåòðà, êîòîðûé áóäåò âñåãî ëèøü èìåòü äâà çíà÷åíèÿ false/true. Òîãäà ïóñêàé ýòîò ïàðàìåòð äîïîëíèòåëüíî õðàíèò èíôîðìàöèþ î ñïîñîáå ãåíåðàöèè òåêñòóðíûõ êîîðäèíàò íàëîæåíèÿ è íàçûâàåòñÿ Textured, ãäå çíà÷åíèå texNone îçíà÷àëî áû, ÷òî òåêñòóðà âûêëþ÷åíà, çíà÷åíèå texFixed – ÷òî òåêñòóðà èìååò ÷¸òêèé ñïèñîê êîîðäèíàò äëÿ òåêñòóðèðîâàíèÿ â íåêîòîðîì ìàññèâå, à çíà÷åíèÿ texObjLinear, texEyeLinear è texSphereMap îçíà÷àëè áû, ÷òî òåêñòóðíûå êîîðäèíàòû äîëæåí ãåíåðèðîâàòü àêñåëåðàòîð ñàìîñòîÿòåëüíî ïî ñîîòâåòñòâóþùèì ìåòîäàì. Äëÿ çàäàíèÿ âèäà òåêñòóðíîãî íàòÿæåíèÿ íà ïîâåðõíîñòü îáúÿâëÿåì êîíñòàíòû texNone, texFixed, texObjLinear, texEyeLinear è texSphereMap ñî çíà÷åíèÿìè îò 0 äî 4 ñîîòâåòñòâåííî. Åñëè êîîðäèíàòû òåêñòóðû íå ôèêñèðîâàíû, òî âêëþ÷àåì ðåæèì àâòî-ãåíåðàöèè òåêñòóðíûõ êîîðäèíàò àêñåëåðàòîðîì
glEnable( GL_TEXTURE_GEN_S );
glEnable( GL_TEXTURE_GEN_T );
è âûáèðàåì ìåòîä ãåíåðèðîâàíèÿ êîîðäèíàò
case Textured of
texObjLinear: Tmp := GL_OBJECT_LINEAR;
texEyeLinear: Tmp := GL_EYE_LINEAR;
else Tmp:=GL_SPHERE_MAP; // äëÿ texSphereMap
end; // case
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, Tmp );
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, Tmp );
Äëÿ íà÷àëà ñëåäóåò ñêàçàòü, ÷òî âîïðåêè òîìó, ÷òî â ðàçíûõ ñòàòüÿõ ìåíÿ ó÷èëè, ÷òî ïîâåðõíîñòü èìååò íåêîòîðûå ñâîéñòâà, íà ïðàêòèêå îêàçàëîñü, ÷òî íà ñàìîì äåëå ýòî êàê ðàç òåêñòóðà ìîæåò èìåòü òå ñàìûå ñâîéñòâà, òàêèå êàê ïîâòîðÿåìîñòü, èëè íå ïîâòîðÿåìîñòü èçîáðàæåíèÿ òåêñòóðû ïî ïîâåðõíîñòè, òî åñòü åñëè áû ÿ ñîçäàâàë êëàññ TGLTexture, à ìû ñåé÷àñ êàê ðàç ýòèì è çàíÿòû ;), òî îí áû ó ìåíÿ îáÿçàòåëüíî ñîäåðæàë ïàðàìåòðû TexRepeatS, TexRepeatT ñîîòâåòñòâåííî ïî øèðèíå è âûñîòå òèïà TGLTexRepeat ñ îïèñàíèåì
type TGLTexRepeat = ( repClamp, repRepeat, repClampToEdge,
repClampToBorder, repMirroredRepeat );
Óñòàíàâëèâàåì ðåæèì ïîâòîðÿåìîñòè òåêñòóðû äëÿ àâòî-ãåíåðàöèè
case TexRepeatS of
repClamp : NowTexRepS := GL_CLAMP;
repRepeat : NowTexRepS := GL_REPEAT;
repClampToEdge : NowTexRepS := GL_CLAMP_TO_EDGE;
end;
case TexRepeatT of
…
end;
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, NowTexRepS );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, NowTexRepT );
À âîò è ïåðâàÿ õèòðîñòü – ýòî ïàðû ïàðàìåòðîâ TexWidthScale, TexHeightScale è TexWidthOffset, TexHeightOffset, ãäå ïåðâàÿ ñîäåðæèò êîýôôèöèåíòû ìàñøòàáèðîâàíèÿ òåêñòóðû ïðè íàëîæåíèè, à âòîðàÿ ïàðà õðàíèò ñìåùåíèå òåêñòóðû ïî ïîâåðõíîñòè. Ïðè÷¸ì âåëè÷èíû ýòè äîëæíû áûòü çàäàíû â êîëè÷åñòâå òåêñòóðû, òî åñòü, TexWidthScale=2 îçíà÷àåò, ÷òî ïî øèðèíå òåêñòóðó ñëåäóåò óäâîèòü, òî áèøü ïîâòîðèòü äâàæäû, à TexWidthScale=0.5 – òåêñòóðó íàëîæèòü òîëüêî ïåðâîé ïîëîâèíîé å¸ èçîáðàæåíèÿ. Àíàëîãè÷íî äëÿ TexWidthOffset=0.5, òîëüêî â äàííîì ñëó÷àå òåêñòóðà áóäåò íå ìàñøòàáèðîâàíà, à ñäâèíóòà ïî ïîâåðõíîñòè íà ïîëîâèíó ñâîåãî ðèñóíêà ïî øèðèíå. Ïðè ýòîì çíà÷åíèÿ ïàðàìåòðîâ îáîèõ ïàð ìîãóò áûòü êàê ïîëîæèòåëüíûìè, òàê è îòðèöàòåëüíûìè. Çà ñ÷¸ò ýòèõ ïàðàìåòðîâ äîñòèãàåòñÿ ýôôåêò îêíà â ïðåäåëàõ òåêñòóðû, è êàêàÿ ÷àñòü èçîáðàæåíèÿ ïîïàäàåò â ýòî îêíî, òà è íàêëàäûâàåòñÿ íà ïîâåðõíîñòü. Óìåëî èñïîëüçóÿ ýòè ÷åòûðå ïàðàìåòðà, ìîæíî ñ ë¸ãêîñòüþ äîáèòüñÿ àíèìàöèè èçîáðàæåíèÿ íà ïîâåðõíîñòè, ïðèìåíèâ òåêñòóðó, ñîñòîÿùóþ èç íåñêîëüêèõ êàðòèíîê, îáúåäèí¸ííûõ â îäíó åäèíóþ ëåíòó ïî øèðèíå, ëèáî ïî âûñîòå è çàòåì ñäâèãàÿ òåêñòóðíîå îêíî ïî òàêîé ëåíòå. Ïðèìåð ïîäîáíîé òåêñòóðû ïîêàçàí íà ðèñ. 4
 äàííîì ñëó÷àå äëÿ ôîðìèðîâàíèÿ òåêñòóðíîãî îêíà ñëåäóåò ïàðàìåòð TexWidthScale óñòàíîâèòü â çíà÷åíèå 0.125, ïîñêîëüêó â ëåíòå òåêñòóðû ñîäåðæàòüñÿ 8 ôðàãìåíòîâ àíèìàöèè ïëàìåíè è, ñòàëî áûòü, ÷òîáû êàæäûé ðàç íà ïîâåðõíîñòè áûë âèäåí òîëüêî îäèí èç íèõ, ñëåäóåò òåêñòóðíîå îêíî ïî øèðèíå óìåíüøèòü äî 1/8. À ÷òîáû îæèâèòü ïëàìÿ, äîñòàòî÷íî ïåðèîäè÷åñêè ñäâèãàòü îêíî íà âåëè÷èíó 0.125, òî åñòü ïîñòîÿííî íàðàùèâàòü ïàðàìåòð TexWidthOffset íà ýòî çíà÷åíèå.
Åñëè êîîðäèíàòû òåêñòóðû ôèêñèðîâàíû, òî îòêëþ÷àåì ðåæèì àâòî-ãåíåðàöèè òåêñòóðíûõ êîîðäèíàò ñëåäóþùèì êîäîì
glDisable( GL_TEXTURE_GEN_S );
glDisable( GL_TEXTURE_GEN_T );
è ïðèìåíÿåì ñäâèã è ìàñøòàáèðîâàíèå êîîðäèíàò òåêñòóðû
glMatrixMode( GL_TEXTURE );
glLoadIdentity;
glTranslatef( TexWidthOffset, TexHeightOffset, 0);
glScalef( TexWidthScale, TexHeightScale, 1);
glMatrixMode( GL_MODELVIEW );
Ïîñêîëüêó òåêñòóðó ìîæíî íàêëàäûâàòü ñî ñãëàæèâàíèåì, èëè áåç íåãî, òî ïàðàìåòðó TexSmooth òîæå áûòü. Òîãäà ðåæèì ôèëüòðàöèè òåêñòóðû óñòàíàâëèâàåì òàê
if TexSmooth then NowTexSmooth := GL_LINEAR
else NowTexSmooth := GL_NEAREST;
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_ MAG_FILTER, NowTexSmooth );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_ MIN_FILTER, NowTexSmooth );
Ïîìèìî ýòîãî òåêñòóðó ìîæíî íàêëàäûâàòü ñî ñìåøåíèåì öâåòîâ, è ïðî÷èìè ýôôåêòàìè íàïîäîáèå Bump-mapping, òî ïàðàìåòð TexEnvMode ïðîñòî íåîáõîäèì.
Õî÷ó îáðàòèòü âíèìàíèå íà òî, ÷òî â ñëó÷àå ïðèìåíåíèÿ ê ïîâåðõíîñòè íå îäíîé, à äâóõ è áîëåå òåêñòóð, ãäå îäíà ÿâëÿåòñÿ îáû÷íîé îêðàøèâàþùåé òåêñòóðîé, à äðóãàÿ Bump-òåêñòóðîé, òî ïåðâîé ñëåäóåò óêàçûâàòü (àêòèâèçèðîâàòü) Bump-òåêñòóðó, èíà÷å ýôôåêò Bump-mapping íå ñðàáîòàåò èëè ñðàáîòàåò ñêîðåå âñåãî êàê ýôôåêò Light-mapping. Áóäó÷è âòîðîé Bump-òåêñòóðà áóäåò èíòåðïðåòèðîâàíà àêñåëåðàòîðîì êàê îáû÷íàÿ Light-map òåêñòóðà, ïîñêîëüêó äëÿ ýòèõ äâóõ ýôôåêòîâ ïðèìåíÿåòñÿ îäíà è òà æå êîìàíäà glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ).
Íà ðèñ. 1 è 2 âèäíî, êàêîãî ýôôåêòà ìîæíî äîñòè÷ü, èñïîëüçóÿ Light-mapping.
Íà ðèñ. 3 ìîæíî óâèäåòü, êàêîãî ýôôåêòà ìîæíî äîñòè÷ü, èñïîëüçóÿ Bump-mapping. Ïðè ýòîì ýôôåêò áóäåò îùóòèì â òîì ñëó÷àå, êîãäà ìåæäó ëó÷îì èñòî÷íèêà ñâåòà è ïëîñêîñòüþ ïîâåðõíîñòè áóäåò ìèíèìàëüíûé óãîë, òî åñòü ìåíåå 90 ãðàäóñîâ. Ëèøü â òàêîì ñëó÷àå àáñîëþòíî ïëîñêàÿ ïîâåðõíîñòü ìîæåò âûãëÿäåòü êàê áû ðåëüåôíîé, òî áèøü îáú¸ìíîé è òàêàÿ ñöåíà áóäåò êàçàòüñÿ áîëåå äåòàëüíîé, ÷åì, åñëè áû íà òåêñòóðå ïîâåðõíîñòè ïðîñòî áûëè íàðèñîâàíû øåðîõîâàòîñòè. Ó÷èòûâàÿ âûøå ñêàçàííîå, óñòàíàâëèâàåì ðåæèì ñìåøèâàíèÿ öâåòîâ
case TexEnvMode of
0: NowTexModulate := GL_DECAL;
1: NowTexModulate := GL_MODULATE;
2: NowTexModulate := GL_BLEND;
3: NowTexModulate := GL_REPLACE;
else NowTexModulate := GL_ADD; // äëÿ Bump-mapping è Light-mapping
end; // case
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, NowTexModulate );
Òåïåðü íåìíîãî ïîôàíòàçèðóåì íàä êëàññîì ïîâåðõíîñòè, è ïðåäïîëîæèì, ÷òî êëàññ ñîäåðæèò ñïèñêè âñåõ ñîñòàâëÿþùèõ òðåóãîëüíèêîâ è èõ íîðìàëåé, âõîäÿùèõ âåðøèí è, åñëè íóæíî, ñãëàæèâàþùèõ íîðìàëåé äëÿ êàæäîé âåðøèíû, à òàêæå ñïèñêè òåêñòóðíûõ òðåóãîëüíèêîâ è òåêñòóðíûõ âåðøèí. Ïðè÷¸ì êàæäûé òðåóãîëüíèê õðàíèòñÿ â âèäå òðèàäû èíäåêñîâ âåðøèí, âõîäÿùèõ â íåãî, à èíäåêñ âåðøèíû – ýòî íè ÷òî èíîå, êàê ïîðÿäêîâûé íîìåð âåðøèíû â ñïèñêå âåðøèí, òî áèøü â ìàññèâå. Ïðè ýòîì êîëè÷åñòâî òðåóãîëüíèêîâ ïîâåðõíîñòè âñåãäà ðîâíÿåòñÿ êîëè÷åñòâó òåêñòóðèðîâàííûõ òðåóãîëüíèêîâ.
Äëÿ ñîñòàâëåíèÿ ìåòîäà ðèñîâàíèÿ ïîâåðõíîñòè ñîñòàâèì ñõåìó äåéñòâèé:
1  íåêîòîðóþ ëîêàëüíóþ ïåðåìåííóþ, ñêàæåì NowTextur, çàíîñèì êîëè÷åñòâî òåêñòóð ñî çíà÷åíèåì íå ðàâíûì texNone ïàðàìåòðà Textured, òî åñòü, ïî ñóòè – êîëè÷åñòâî àêòèâíûõ òåêñòóð, êîòîðûå ñëåäóåò íàëîæèòü íà ïîâåðõíîñòü.
2 Ïðîâåðÿåì äîñòóïíîñòü ìóëüòèòåêñòóðèðîâàíèÿ, ïðî÷èòàâ çíà÷åíèå ïàðàìåòðà GL_ARB_multitexture ñðåäû OpenGL. Åñëè äîïóñòèìî íàëîæåíèå òîëüêî îäíîé òåêñòóðû, òî êîëè÷åñòâî àêòèâèçèðóåìûõ òåêñòóð â NowTextur è ìàêñèìàëüíîå äîïóñòèìîå êîëè÷åñòâî òåêñòóð â NowMaxTextur óñòàíàâëèâàåì â îäèí. Ïîñëå ÷åãî ñëåäóåò âûçâàòü ìåòîä BindTexture ïåðâîé àêòèâíîé òåêñòóðû ïî ñïèñêó.
3 Åñëè ìóëüòèòåêñòóðèðîâàíèå âîçìîæíî, òî â ñëó÷àå, êîãäà êîëè÷åñòâî àêòèâèçèðóåìûõ òåêñòóð â NowTextur ïðåâûøàåò ìàêñèìàëüíî äîïóñòèìîå êîëè÷åñòâî òåêñòóð â GLMaxTextureUnits (ïàðàìåòð ñðåäû OpenGL) äëÿ îäíîâðåìåííîãî íàëîæåíèÿ íà äàííîì àêñåëåðàòîðå, òî ïàðàìåòð NowMaxTextur óñòàíàâëèâàåì â äîïóñòèìûé ìàêñèìóì äëÿ àêñåëåðàòîðà, èíà÷å çàíîñèì çíà÷åíèå NowTextur â ëîêàëüíóþ ïåðåìåííóþ NowMaxTextur.
Ïîñëå ÷åãî ïåðåáèðàåì ïî ñïèñêó âñå òåêñòóðû, è êîäîì
glActiveTextureARB( GL_TEXTURE0_ARB + k );
Texture[ j ].BindTexture;
àêòèâèçèðóåì òîëüêî àêòèâíûå, ïðè÷¸ì ïåðåìåííàÿ j èíäåêñèðóåò òåêñòóðû ïî ñïèñêó îò íóëÿ, à ïåðåìåííàÿ k âåä¸ò ñ÷¸ò ïîäêëþ÷àåìûõ òåêñòóð îò íóëÿ.
Ïðåæäå, ÷åì ïåðåéòè íåïîñðåäñòâåííî ê ðåíäåðèíãó, íåîáõîäèìî ñîñòàâèòü âñïîìîãàòåëüíóþ ïðîöåäóðó procedure TexCoord2f ( U, V : GLFloat ), êîòîðàÿ äîëæíà áóäåò çàíîñèòü íà îáðàáîòêó êîîðäèíàòû î÷åðåäíîé òåêñòóðíîé âåðøèíû. Ïðè ìóëüòèòåêñòóðèðîâàíèè â ñëó÷àå îäíîé àêòèâíîé òåêñòóðû äîñòàòî÷íî âûçûâàòü êîìàíäó glMultiTexCoord2fARB( GL_TEXTURE0_ARB, U, V ). Åñëè æå àêòèâíûõ òåêñòóð íåñêîëüêî, òî ïåðåáèðàÿ èõ ïî ñïèñêó è îòûñêèâàÿ àêòèâíûå ñ ôèêñèðîâàííûìè êîîðäèíàòàìè (êîãäà Texture[ j ].Textured = texFixed) âûçûâàòü ñëåäóåò êîìàíäó glMultiTexCoord2fARB( GL_TEXTURE0_ARB + k, U, V ), ãäå k âåä¸ò ó÷¸ò àêòèâíûõ òåêñòóð.
Ñëåäóåò ïîìíèòü, ÷òî â ñëó÷àå íåäîñòóïíîñòè ìóëüòèòåêñòóðèðîâàíèÿ, âî èçáåæàíèå ñáîÿ, çàäàâàòü êîîðäèíàòû âåðøèí òåêñòóðû ñëåäóåò òîëüêî ñòàðîé êîìàíäîé glTexCoord2f.
Òåïåðü ìîæíî ïðèñòóïèòü íåïîñðåäñòâåííî ê ðåíäåðèíãó.
glBegin( GL_TRIANGLES );
// Èä¸ì ïî ñïèñêó òðåóãîëüíèêîâ
for j := 0 to FaceCount-1 do begin
glNormal3fv(…);
if NowTextur > 0 then begin
// Ïîëó÷àåì òðèàäó èíäåêñîâ òåêñòóðíûõ âåðøèí î÷åðåäíîãî òðåóãîëüíèêà
NowTFace := TexFace[j];
TexCoord2f( TexVertex[NowTFace[0>.u, TexVertex[NowTFace[0>.v );
end;
glVertex3fv(…);
if NowTextur > 0 then TexCoord2f( TexVertex[NowTFace[1>.u, TexVertex[NowTFace[1>.v );
glVertex3fv(…);
if NowTextur > 0 then TexCoord2f( TexVertex[NowTFace[2>.u, TexVertex[NowTFace[2>.v );
glVertex3fv(…);
end;
glEnd;
Ïîñëå çàâåðøåíèÿ ðèñîâàíèÿ î÷åðåäíîé ïîâåðõíîñòè ñëåäóåò îòêëþ÷èòü ðåæèì òåêñòóðèðîâàíèÿ, ÷òîáû ïðè ðèñîâàíèè ñëåäóþùåé ïîâåðõíîñòè äàííûé ðåæèì íå âëèÿë. Ñ îäíîé òåêñòóðîé âñ¸ ïðîñòî
glActiveTextureARB( GL_TEXTURE0_ARB );
glDisable( GL_TEXTURE_2D );
Èíà÷å íåîáõîäèìî îòêëþ÷èòü âñå âêëþ÷¸ííûå òåêñòóðû
for j := 0 to NowTextur-1 do begin
glActiveTextureARB( GL_TEXTURE0_ARB + j );
glDisable( GL_TEXTURE_2D );
end;
Ïàðàìåòðû ñðåäû OpenGL
GLMaxTextureUnits - ãëîáàëüíàÿ ïåðåìåííàÿ òèïà Integer (GLint) è å¸ çíà÷åíèå ïîëó÷àåì îäèí ðàç ïðè èíèöèàëèçàöèè ïðîãðàììû êîìàíäîé glGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, @GLMaxTextureUnits ). Ÿ çíà÷åíèå ïîêàçûâàåò êîëè÷åñòâî òåêñòóð, êîòîðûå ìîæíî íàíåñòè íà ïîâåðõíîñòü îäíîâðåìåííî. Íàïðèìåð, äëÿ àêñåëåðàòîðà TNT2 Pro 32MB ýòîò ïàðàìåòð ðîâíÿåòñÿ äâóì.
Ïîìèìî ýòîãî ñëåäóåò ïîëó÷èòü àäðåñà êîìàíä:
glMultiTexCoord1fARB := wglGetProcAddress('glMultiTexCoord1fARB');
glMultiTexCoord2fARB := wglGetProcAddress('glMultiTexCoord2fARB');
…
glActiveTextureARB := wglGetProcAddress('glActiveTextureARB');
ãäå îíè îïèñàíû êàê
var
glMultiTexCoord1fARB : procedure(target: GLenum; s: GLfloat); stdcall;
glMultiTexCoord2fARB : procedure(target: GLenum; s, t: GLfloat); stdcall;
glMultiTexCoord3fARB : procedure(target: GLenum; s, t, r: GLfloat); stdcall;
glMultiTexCoord4fARB : procedure(target: GLenum; s, t, r, q: GLfloat); stdcall;
glActiveTextureARB : procedure(target: GLenum); stdcall;
Ïàðàìåòð GL_ARB_multitexture òèïà boolean ìîæíî ïîëó÷èòü ïðè ïîìîùè ñëåäóþùåãî êîäà, áëàãîäàðÿ ÷åìó ìîæíî âûÿñíèòü, ïîääåðæèâàåòñÿ ëè ìóëüòèòåêñòóðèðîâàíèå äàííûì àêñåëåðàòîðîì:
function CheckExtension( const Extension : String ) : boolean;
begin
Result := Pos( Extension, Buffer ) > 0;
end;
procedure ReadAllExtensions;
var Buffer : String;
begin
Buffer := glGetString( GL_EXTENSIONS );
GL_ARB_multitexture := CheckExtension( 'GL_ARB_multitexture' );
GL_EXT_fog_coord := CheckExtension( 'GL_EXT_fog_coord' );
…
end;
Ïðîøó îáðàòèòü âíèìàíèå íà ñòðîêó GL_EXT_fog_coord := CheckExtension( 'GL_EXT_fog_coord' ), êîòîðàÿ ïîçâîëÿåò îïðåäåëèòü ïîääåðæèâàåòñÿ ëè îáú¸ìíûé òóìàí äàííûì àêñåëåðàòîðîì. Ñêîðî îíà íàì ïîíàäîáèòñÿ.
Îáú¸ìíûé GL-òóìàí
ß íå áóäó âäàâàòüñÿ â ïîäðîáíîå îïèñàíèå íàñòðîéêè ïàðàìåòðîâ òóìàíà, î êîòîðûõ è òàê ìîæíî ïðî÷åñòü â ëþáîé ñòàòüå äëÿ íà÷èíàþùèõ, íî äîëæåí ñêàçàòü, ÷òî ïî óìîë÷àíèþ âêëþ÷¸í îáû÷íûé ãëîáàëüíûé òóìàí, â ñîìíèòåëüíîé ðåàëèñòè÷íîñòè êîòîðîãî è òàê âñå óæå ìîãëè óáåäèòüñÿ. ×òîáû èñïîëüçîâàòü îáú¸ìíûé òóìàí ñëåäóåò çàðàíåå óäîñòîâåðèòüñÿ, ÷òî îíûé ïîääåðæèâàåòñÿ, òî åñòü ïðîâåðèòü ïåðåìåííóþ GL_EXT_fog_coord, è ëèøü çàòåì âûïîëíèòü ñëåäóþùóþ êîìàíäó
glFogi( GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT );
à ÷òîáû ïðè íåîáõîäèìîñòè âåðíóòüñÿ ñíîâà ê îáû÷íîìó òóìàíó, òî äîñòàòî÷íî âûïîëíèòü êîìàíäó
glFogi( GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT );
×òîáû ðàáîòàòü ñ îáú¸ìíûì òóìàíîì, ñëåäóåò ïðîñ÷èòàòü âåëè÷èíó åãî èíòåíñèâíîñòè äëÿ êàæäîé âåðøèíû êàæäîãî òðåóãîëüíèêà îáúåêòà, êîòîðûé ïðåäïîëîæèòåëüíî íàõîäèòñÿ â òóìàíå èëè çà íèì, òî åñòü êàê áû â çîíå òóìàíà. Âû÷èñëåíèÿ ýòè ìîæíî äåëàòü êàê óãîäíî, èç ðàñ÷¸òà, íàïðèìåð, ÷òî îáúåêò áóäåò âñåãäà íàõîäèòüñÿ íà ñâî¸ì ìåñòå è, çíà÷èò, èíòåíñèâíîñòü òóìàíà äëÿ êàæäîé âåðøèíû äîñòàòî÷íî ïðîñ÷èòàòü âñåãî îäèí ðàç. Èíà÷å, åñëè, äîïóñòèì, òóìàí ñòåëåòñÿ ïî ãîðèçîíòàëüíîé ïîâåðõíîñòè, è íà ýòîé ïîâåðõíîñòè ëåæèò îáúåêò, êîòîðûé ìîæåò ïåðåìåùàòüñÿ ââåðõ è âíèç, è âåðîÿòíî ìîæåò âûéòè èç îáëàñòè òóìàíà, òî, ñëåäîâàòåëüíî, íåîáõîäèìî ïðè êàæäîì ïåðåìåùåíèè âû÷èñëÿòü íîâóþ èíòåíñèâíîñòü òóìàíà äëÿ êàæäîé âåðøèíû îáúåêòà. Ïîìèìî ýòîãî ìîæíî ñîçäàòü ýôôåêò òàêîãî òóìàíà, êîòîðûé áû ðàññòóïàëñÿ âáëèçè êàìåðû íà îïðåäåë¸ííûé ðàäèóñ, òîãäà äëÿ âû÷èñëåíèÿ èíòåíñèâíîñòè òàêîãî òóìàíà íåîáõîäèì äðóãîé àëãîðèòìè÷åñêèé ïîäõîä, íî ýòî óæå ÷èñòàÿ ìàòåìàòèêà.
Ñëåäóåò îòìåòèòü, ÷òî ÷åì áîëüøå òðåóãîëüíèêîâ ñîäåðæèò â ñåáå îáúåêò, ïîìåùàåìûé â òóìàí, òåì ðåàëèñòè÷íåå áóäåò ñàì òóìàí. Èíà÷å îáûêíîâåííûé êâàäðàò, ñîñòîÿùèé âñåãî èç ÷åòûð¸õ âåðøèí íè â ìàëåéøåé ìåðå íå ñîçäàñò ýôôåêò òóìàíà, ïîñêîëüêó ÷åòûðå âåðøèíû äàþò ñëèøêîì ìàëóþ “ïèùó” äëÿ âû÷èñëåíèé â àêñåëåðàòîðå. È ñîâñåì äðóãîå äåëî, åñëè áû ýòîò êâàäðàò ñîñòîÿë èç ñåòêè êâàäðàòîâ õîòÿ áû 10x10, òî ýôôåêò îáú¸ìíîãî òóìàíà ñòàë áû îùóòèìåå.
Íà ðèñóíêàõ 5 è 6 ïîêàçàíà ñöåíà áåç òóìàíà è ñ òóìàíîì â ïîìåùåíèè (íó è ïûëèùè òàì ;) ). Ãäå, íà âàø âçãëÿä, ñöåíà âûãëÿäèò ëó÷øå?
Íà ðèñóíêàõ 7 è 8 ïðåäñòàâëåíà ñöåíà áåç òóìàíà è ñ òóìàíîì íà îòêðûòîì ïðîñòðàíñòâå. Íà ðèñ. 7 âîçäóøíàÿ àòìîñôåðà âèçóàëüíî ïðàêòè÷åñêè íå óëàâëèâàåòñÿ, à íà ðèñóíêå 8 òóìàí äåëàåò ñöåíó ìÿã÷å è âîçäóõ íàñûùåííûì. Ãäå, íà âàø âçãëÿä, ñöåíà âûãëÿäèò åñòåñòâåííåå?
Èòàê ìû ïðèøëè ê âûâîäó, ÷òî äëÿ êëàññà ïîâåðõíîñòè íåîáõîäèì ïàðàìåòð Foging : boolean, îòâå÷àþùèé çà âëèÿíèå òóìàíà íà îáúåêò è ñïèñîê èíòåíñèâíîñòè òóìàíà â êàæäîé âåðøèíå îáúåêòà, òî áèøü ìàññèâ ýëåìåíòîâ âåùåñòâåííîãî òèïà. Òîãäà ôðàãìåíò êîäà, ðåàëèçóþùåãî âñ¸ âûøå ñêàçàííîå, âûãëÿäèò òàê
// Âêëþ÷àåì âëèÿíèå òóìàíà íà ðåíäåðèíã äàííîãî îáúåêòà
if Foging then glEnable( GL_FOG );
glBegin( GL_TRIANGLES );
// Èä¸ì ïî ñïèñêó òðåóãîëüíèêîâ
for j := 0 to FaceCount-1 do begin
glNormal3fv(…);
if Foging then glFogCoordfEXT(…);
glVertex3fv(…);
if Foging then glFogCoordfEXT(…);
glVertex3fv(…);
if Foging then glFogCoordfEXT(…);
glVertex3fv(…);
end;
glEnd;
Åñëè òóìàí áûë ïðèìåí¸í, òî ñëåäóåò èñêëþ÷èòü íåñàíêöèîíèðîâàííîå âëèÿíèå òóìàíà íà ñëåäóþùèå îáúåêòû
if Foging then glDisable(GL_FOG);
Ïðåäâàðèòåëüíî ïðè èíèöèàëèçàöèè ïðîãðàììû ñëåäóåò íå çàáûòü ïîëó÷èòü àäðåñ êîìàíäû glFogCoordfEXT := wglGetProcAddress( 'glFogCoordfEXT' ), ãäå îíà îïèñàíà êàê var glFogCoordfEXT : procedure ( coord : single ); stdcall;
Äóìàþ, òåïåðü òóìàí íåäîñòàòêà èíôîðìàöèè ïî OpenGL íåìíîãî ðàññååòñÿ ;)
Âîò ñîáñòâåííî è âñ¸, ÷òî ÿ èìåë ñêàçàòü.
P.S.
|