Gry 3D - dynamiczne światła, OpenGL

Komorkowy_dzony

Przed przystąpieniem do kopiowania kodu, trzeba zaopatrzyć się w biblioteki: GLext.pas, gl.pas, dglOpenGL.pas ten ostatni moze pomieszać wam proces inicjalizacji trybu opengl, te nagłówki zawierają dużo rzeczy, których nie trzeba już ponownie pisać, bo w wiekszości to są odwołania do funkcji w DLL'kach opengl

NIe muszy chyba mówić, że gdy stworzymy sobie klase tswiatlo ktora bedzie miała takie rzeczy jak pozycja, zasięg światła, kolor światla itp. po prostu będziemy zmieniali te parametry światłą które chcemy i wszystko będzie się inaczej rysowało (czyli zmieniamy kolor z bialego na niebieski i mamy niebiesko na ekrtanie :0)<font size="4"></span>

Technika polega na narysowaniu kolejno całej oświetlonej sceny z włączonym blendowaniem, z tym że ustawiamy trójwymiarową teksturę (światło) w pozycji światła i zmieniamy kolory.

Od razu piszę wam, że nie znajdziecie tutaj techniki rysowania cieni ponieważ sam ją dopracowywuję.

Małe objaśnienie: światło punktowe to trójwymiarowa tektura nałożona na obiekt!

Oczywiście będzie trzeba to później zoptymalizować pod względem predkości działania, zalecam używać komputerów z procesorami 64-bitowymi (np. AMD Athlon 64) i kartami graficznymi z serii GeForce (od 6600)

Pewna część tego kodu została przerobiona z sampla ściągniętego z internetu, wbrew pozorm nie było łatwe przerobienie tego na więcej niż jedno światło.

Na wstępie musze zaznaczyć, że miło by było jakbyście sobie ściągneli plik: GLext.pas chodzi o to, że podczas inicjowania świateł wystapią błędy typu undeclarated indentifier..

Na razie w tym artykule będzie tylko o światłach punktowych, później się dopisze resztę.
A więc tak musimy zdefiniować światło jako rekord. (musimy uwzględnić kilka szczegółów tzn. Pozycja światła, promień światła - to są podstawowe wartości; plus do tego kolor światła i inne bzdety) Ustalmy, że stworzyliśmy też rekord punktu t3dpoint

type t3dpoint = record
x: single;
y: single;
z: single;
end;

type t4dpoint = record //o tym później
x : single;  //also r
y : single;  //also g
z : single;  //also b
a : single;
end;

type tswiatlo = record
pozycja : t3dpoint;
zasieg   : single;

Do globlanych const dodajemy
PL_SIZE = 64;
PS: array [0..3] of Single = ( 1, 0, 0, -1 );
PT: array [0..3] of Single = ( 0, 1, 0, -1 );
PR: array [0..3] of Single = ( 0, 0, 1, -1 );

Ok to już mamy w sumie wszystko do narysowania światła, potrzebujemy jeszcze tylko funkcji inicjującej multiteksturing, procedury rysującej daną scenę trzeba ją umieścić w tym kodzie, ale to później:

Zainicjujmy światła: (trzeba wywołać tą funkcję podczas glinit), lecz przed tym dodaj przed implementation procedure: function wglGetProcAddress(proc: PChar) : Pointer; stdcall; external 'OpenGL32.dll';

a do globalnego var
glActiveTextureARB : procedure (target:GLenum); stdcall;
glMultiTexCoord2fARB : procedure (target:GLenum;u,v:GLfloat); stdcall;

No to zainicjujmy światła

procedure initialize_lights;
var
x,y,z : integer;
v : t4dpoint;
i: Single;
const
  PLS2 = PL_SIZE / 2;
begin
//tutaj pobieramy adresy z dll'ek żeby ustawić bodajże wskaźniki
     glMultiTexCoord2fARB := wglGetProcAddress('glMultiTexCoord2fARB');
    glMultiTexCoord2fvARB := wglGetProcAddress('glMultiTexCoord2fvARB');
    glActiveTextureARB := wglGetProcAddress('glActiveTextureARB');
glTexImage3D := wglGetProcAddress('glTexImage3D');


glActiveTextureARB(GL_TEXTURE1_ARB); //ta linijka jest dośc dziwna ale dzięki niej będziemy w stanie narysować coś i nie usuwać wszczśniej narysowanej sceny :] małe wyjaśnienie przechodzimy z GL_TEXTURE0_ARB na GL_TEXTURE1_ARB, z jednej jednostki renderujacej do drugiej

    glEnable(GL_TEXTURE_3D);//włączamy mapowanie tektur 3D
//GL_TEXTURE_GEN to jest automatyczne mapowanie tektury na tym co rysujemy fajne efekty można dzięki temu zrobić (poprzez skalowanie i translacje w glmatrixmode(GL_TEXTURE); :S ale to nie ten artykul
    glEnable(GL_TEXTURE_GEN_S); 
    glEnable(GL_TEXTURE_GEN_T);
    glEnable(GL_TEXTURE_GEN_R);

//tutaj już ustawiamy teksturę światła
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
    glTexGenfv(GL_S, GL_OBJECT_PLANE, @PS);
    glTexGenfv(GL_T, GL_OBJECT_PLANE, @PT);
    glTexGenfv(GL_R, GL_OBJECT_PLANE, @PR);

    // Create volume texture: jak sama nazwa wskazuje tworzymy adres w pamięci dla tekstury
    glGenTextures(1, PLTexObj);
    glBindTexture(GL_TEXTURE_3D, PLTexObj); //bindowanie tekstury aby opengl wiedział, którą ma używać

    for x := 0 to PL_SIZE-1 do
    begin
      for y := 0 to PL_SIZE-1 do
      begin
        for z := 0 to PL_SIZE-1 do
        begin

          v := <b>d4dsingletopoint</b>((x - PLS2)/PLS2, (y - PLS2)/PLS2, (z - PLS2)/PLS2); //o tej funkcji bedzie niżej
          i := 255 * <b>magnitude4d</b>(v) * sqrt(3);//o tej też
          if i > 255 then i := 255;                   // PointLight[x,y,z] := abs(0 - round(i)); <- dobry efekt
   PointLight[x,y,z] := 255 - round(i); //        PointLight[x,y,z] := 255 - round(i);  <- podstawowa tekstura swiatla!!
        end;
      end;
    end;

    glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE8, PL_SIZE, PL_SIZE, PL_SIZE, 0,
                 GL_LUMINANCE, GL_UNSIGNED_BYTE, @PointLight);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);





    gldisable(GL_TEXTURE_3D);
gldisable(GL_TEXTURE_GEN_S);
gldisable(GL_TEXTURE_GEN_T);
gldisable(GL_TEXTURE_GEN_R);

    glActiveTextureARB(GL_TEXTURE0_ARB);   //powracamy z ARB1 na ARB0 (czyli tego co zmieniliśmy na początku)

end;

Ta funkcja rysuje na trójwymiarowej teksturze odpowiednie punkty

Teraz co nieco o:
d4dsingletopoint
i magnitude4d
Niestey było jakoś tak, że musiałem przerobić funkcje z tego powodu, iż operować trzeba było na 3 wartościach z 4 dlatego przerobiłem to i owo:

function d4dsingletopoint(vx, vy, vz: Single): t4dpoint;
begin

  { Create a TCGVector at [vx, vy, vz]. }
  with Result do
  begin
    x := vx;
    y := vy;
    z := vz;
    a := 1;
  end;

end;

function magnitude4d(Vector : t4dpoint) : single;
begin
Result := sqrt(
(vector.X*vector.X) +
(vector.Y*vector.Y) +
(vector.Z*vector.Z));
end;

ok światła zainicjowane...

możemy przystąpić do rysowania światła, UWAGA jeżeli zastosujemy GL_LIGHT to wtedy glcolor3f lub glcolor4f nie zadziałają! Trzeba będzie ustalić kolor materiału, ale to są już techniki renderowania scen co może napisze w innym artykule.

Poniższy kod jest oryginalnym kodem tnoxx_gllight to tswiatlo, a tglarrayselectionmodel to scena, którą trzeba narysować, radzę przeczytać uwagi pod tym kodem po obejrzeniu kodu.

Od razu wytłumacze co nieco o tej procedurze:

procedure Drawlights(lights : array of tnoxx_gllight; model : array of tglarrayselectionmodel;
mode : byte; enable_blend : boolean;draw_only_alpha_faces : boolean;colormask : boolean;
textured: boolean;enable_GLGLIGHT:boolean; isweapon : boolean);

Mamy tam światła, modele, mode czyli jak rysujemy światło, czy włączyć blendowanie (trzeba), czy rysować tylko przezroczyste ściany (np. szkło) czy zapisujemy to do bufora głębi, a nie gdzie indziej (w sumie jest to zbędne i tego nie użwyam), czy mamy włączyć teksturowanie obiektów (czyli czy mamy widzieć tekstury na naszej scenie lub modelu), i czy włączamy GLLIGHT, ostatnie to jest wartośc logiczna czy model, który rysujemy jest bronią (to z tego powodu, że inaczej się rysuje modele dynamiczne, a inaczej statyczne - to także tyczy mode)

Ważnym jest, żeby sprawdzać przed rysowaniem, jakie światło widzimy, ile jest widocznych świateł itp.
Dodatkowo znajdziecie takie coś jak lc : integer; to nam mówi kiedy mamy przestać rysować mgłę, ponieważ jak ją włączymy to musi zostać ona narysowna raz, a nie kilka razy ( co da nam efekt jasnej jak cholera mgły)

procedure Drawlights(lights : array of tnoxx_gllight; model : array of tglarrayselectionmodel;
<b>mode</b> : byte; enable_blend : boolean;draw_only_alpha_faces : boolean;colormask : boolean;
 textured: boolean;enable_GLGLIGHT:boolean; isweapon : boolean);
var
x : integer;
i  : integer;
kk : boolean;
<b>lc:integer;</b>
j : integer;
MATERIALdiffuse :  array [0..3] of gLfloat;
M: array[0..15] of single;
v:array[0..3] of single;      relativeLightPos : T3DPOINT;   OLDLIGHTPOS: T3DPOINT;
ONE      :  array [0..3] of gLfloat;   done : boolean;
begin
lc:=0;
done := false;
MATERIALdiffuse[0] := 0.5;
MATERIALdiffuse[1] := 0.5;
MATERIALdiffuse[2] := 0.5;
MATERIALdiffuse[3] := 0.5;

kk := false;
ONE[0] := 1;
ONE[1] := 1;
ONE[2] := 1;
ONE[3] := 1;

if textured then glenable(GL_TEXTURE_2D);




if mode = 1 then GLBLENDFUNC(GL_one,GL_ONE_MINUS_SRC_ALPHA);

if colormask then begin
glColorMask(false,false,false,false);
for j:=0 to high(model) do  Cast_the_shadow(model[j]);//,draw_only_alpha_faces,[swiatlo]);
//Cast_the_shadow(weaponsbank[weaponinbank].weaponmodel);//,false,[swiatlo4],old);
//if mode = 0 then draw_CANDLE;
glColorMask(true,true,true,true);
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

glcolor4f(0.5,0.5,0.5,1);

  GLENABLE(GL_BLEND);

if mode <> 2 then //tutaj sprawdzamy czy rysujemy scenę czy dynamiczny model (i jeżeli rysujemy scenę)
if mode <> 3 then (i jeżeli rysujemy scenę)
for j:=0 to high(model) do begin //tutaj jest coś dla misiów czyli rysowanie LIGHTMAP!
glBlendFunc(GL_ONE, GL_ZERO);
DrawglArraySelection(model[j],draw_only_alpha_faces,[lights[0]],old);//rysuj model
glBlendFunc(GL_DST_COLOR, GL_ZERO);
DrawglArraySelectionLIGHTMAP(model[j],draw_only_alpha_faces,[lights[0]],old);//rysuj lightmapy

end;

gldisable(GL_BLEND);

// if draw_dynamic_SCENE=false then exit;  dałem to w komentarz, ale jeżeli nie rysujemy żadnego dynamicznego światła to po co mamy używać kodu poniżej


//teraz coś dla broni dla gier FPP:
 if isweapon then
if TYLE_SWIECI = 0 then begin //jeżeli na broń nie pada żadne światło to się ona nie narysuje dlatego też musimy narysować bron cała ciemna.
glcolor3f(0,0,0);
for j:=0 to high(model) do
DrawglArraySelection(model[j],draw_only_alpha_faces,[lights[0]],old);
END;



///                                           A TERAZ KOD RYSOWANIA ŚWIATEŁ

if enable_blend then glenable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE);


glActiveTextureARB(GL_TEXTURE1_ARB); //przełączamy się na ARB1 z ARB0

    glEnable(GL_TEXTURE_3D);
    glEnable(GL_TEXTURE_GEN_S);
    glEnable(GL_TEXTURE_GEN_T);
    glEnable(GL_TEXTURE_GEN_R);

    glMatrixMode(GL_TEXTURE);
glBindTexture(GL_TEXTURE_3D, PLTexObj); //bindujemy tekture, którą stworzyliśmy w procedurze initialize_lights



for i:=0 to high(lights) do //pętla przez wszystkie światła {mogą to być wszystkie światła na scenie lub w portalu lub po prostu juz wyliczona tablica)

if lights[i].visible = true then  begin //jeżeli światło świeci to:
lc := lc + 1; //jak widzimy światło to dodajemy LC

//if isweapon then
if lc > 0 then gldisable(GL_FOG); i jak już coś narysowaliśmy to wyłączamy mgłę

glActiveTextureARB(GL_TEXTURE1_ARB);
glcolor4f(lights[i].rgba[0],lights[i].rgba[1],lights[i].rgba[2],lights[i].rgba[3]); //to jak nie używamy GLLIGHT ustalamy kolor światła



glloadidentity();
//gltranslate(model[0].translate.x,model[0].translate.y,model[0].translate.z);
glTranslatef(0.5, 0.5, 0.5);

glScalef(lights[i].radius, lights[i].radius, lights[i].radius);//teraz skalujemy światło (czyli jak duże ma być światło) uwaga przy tym bo skalujemy przez małe liczby ale większe od 0! z zakresu np. 0.1 do 0.00001. im liczba jest bliższa zeru tym większe światło

//tutaj przenosimy pozycję światła zeby oświtliła model prawidłowo
if mode = 0 then glTranslatef(-lights[i].poS.x, -lights[i].poS.y, -lights[i].poS.z);
if mode = 3 then glTranslatef(-lights[i].poS.x, -lights[i].poS.y, -lights[i].poS.z);
if mode = 1 then glTranslatef(old.x-lights[i].poS.x,old.y-lights[i].poS.y,old.z-lights[i].poS.z);
if mode = 2 then  begin
  glTranslatef(old.x-lights[i].poS.x,old.y-lights[i].poS.y,old.z-lights[i].poS.z);

end;

glActiveTextureARB(GL_TEXTURE0_ARB);


if enable_GLGLIGHT then begin
glenable(GL_LIGHTING);
glenable(GL_LIGHT0);
//if mode = 2 then
//glLightfv(GL_LIGHT0, GL_POSITION, @relativeLightPos) else
glLightfv(GL_LIGHT0, GL_POSITION, @lights[i].pos);
//glLightfv(GL_LIGHT0, GL_AMBIENT, @LightAmb);
//glLightfv(GL_LIGHT0, GL_DIFFUSE, @MATERIALdiffuse);
//glLightf(gl_light5,GL_SPOT_EXPONENT,strtofloat(w_nawiasie[1]));
glLightfv(GL_LIGHT0, GL_AMBIENT, @MATERIALdiffuse);
glMaterialfv(GL_FRONT, GL_DIFFUSE, @lights[i].rgba);
glMaterialf(GL_FRONT, GL_SPECULAR, 1);
 //glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, @MatSpecular);
 //glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, @tmp);
glEnable( GL_COLOR_MATERIAL);   // glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 1);
// front i tył są zanurzone w świetle otaczającym ...
glColorMaterial( GL_FRONT, GL_AMBIENT);
glColorMaterial( GL_FRONT, GL_DIFFUSE);
glColorMaterial( GL_FRONT, GL_SPECULAR);

//glMaterialfv( GL_FRONT, GL_EMISSION,@lights[i].rgba);


glMateriali(GL_FRONT, GL_SHININESS, 128);
end;

glcolor4f(1,1,1,1);

if not enable_GLGLIGHT then glcolor4f(lights[i].rgba[0],lights[i].rgba[1],lights[i].rgba[2],lights[i].rgba[3]);


if isweapon then if kk = false then gldisable(GL_BLEND);

for j:=0 to high(model) do begin//rusyjemy scenę lub model

DrawglArraySelection(model[j],draw_only_alpha_faces,[lights[1]],old);

DrawglArraySelectionLIGHTMAP(model[j],draw_only_alpha_faces,[lights[1]],old);


end;
if isweapon then  if kk = false then glenable(GL_BLEND);
if kk = false then kk := true;

if enable_GLGLIGHT then begin
gldisable(GL_LIGHTING);
gldisable(GL_LIGHT0);   gldisable( GL_COLOR_MATERIAL);
end;


end;

glActiveTextureARB(GL_TEXTURE1_ARB);

gldisable(GL_TEXTURE_3D);
gldisable(GL_TEXTURE_GEN_S);
gldisable(GL_TEXTURE_GEN_T);
gldisable(GL_TEXTURE_GEN_R);


glMatrixMode(GL_MODELVIEW);
glActiveTextureARB(GL_TEXTURE0_ARB);

 glcolor4f(1,1,1,1);

if enable_blend then gldisable(GL_BLEND);
if textured then gldisable(GL_TEXTURE_2D);

end;

Może to nie jest szczyt moich możliwości opisania kodu, ale nie wiem jak wam to wytłumaczyć lepiej dopiero po komentarzach się dowiem co i jak.

Procedura drawlights rysuje scenę, a później światła (ze sceną, z włączonym blendingiem, aby wszystko było widoczne). Jeszcze jedno apropo mode w procedurze swiatła dynamiczne mają to do tego, że trzeba je przemieścić w odpowiednie miejsce na mapie względem pozycji rysowanego modelu.
zauwazyliscie pewnie if mode = 1 then glTranslatef(old.x-lights[i].poS.x,old.y-lights[i].poS.y,old.z-lights[i].poS.z); old to pozycja gracza Gry rysujemy dynamiczny model to musimy zmienić pozycję światła, względem pozycji modelu (i obrócić światło [zrobić translację])- z tym obracaniem jeszcze nie wykminiłem pomysłu :U

Istnieje kilka możliwości przyśpieszenia rysowania.

Pierwsza to podzielenie świateł dynamicznych na poruszające się i nie.
Zawsze można obliczyć, która ściana jest zwrócona tyłem do swiatła i jej nie rysować znowu) dla świateł nie poruszających o tyle jest to wygodne, że obliczamy te ściany tylko raz, a dla poruszających się może to torchę zwolnić silnik, w zależności jak rysujemy scenę i ile mamy testów do zrobienia), daje to znaczący wzrost FPS.

Inna z kolei metoda to stworzenie VA i VBO czyli tablicy wierzchołków kolorów, koordyantów tekstur i normalnych ścian w jednej tablicy (znaczy te tablice sa osobno np. normalne i wierzchołki) [nie wspominając o pogrupowaniu wierzchołków z tymi samymi teksturami co da nam znaczący wzrosc FPS]

setlength(model.VBO_FACE_INFO,lengtH(model.face));

for i:=0 to high(model.face) do begin
model.VBO_FACE_INFO[i].INDEX_START := n;
model.VBO_FACE_INFO[i].length := model.facelength[i];
for j:=0 to high(model.arrays[i]) do
n :=n + 1;

end;

setlength(model.VBO_V,n);
setlength(model.VBO_N,n);    setlength(model.VBO_LIGHTT,n);
setlength(model.VBO_T,n);
n:=0;
for i:=0 to high(model.face) do

for j:=0 to high(model.arrays[i]) do   begin
model.VBO_V[n]   := model.arrays[i][j].vertex3f;
model.VBO_N[n]   := model.FACE_NORMAL[i];
model.VBO_T[n]  := model.arrays[i][j].texcoord2f;
if model.modelLIGHTMAPPED then model.VBO_LIGHTT[n]  := model.lightarrays[i][j];
n :=n + 1;

end;


model.usesvbo := true;
end;



///typy

type tglArraySelectionModel=record
VBO_V                : array of t3dpoint;
VBO_N                : array of t3dpoint;
VBO_T                : array of textpoint;
VBO_LIGHTT           : array of textpoint;
VBO_FACE_INFO                   : array of tvbofacenfo;  // start index i end index


USESVBO                         : boolean; 
....

type tvbofacenfo=record
INDEX_START : integer;
length : integer;
end;

Dodatkowo można przecież podzielić scenę na różne obszary i tyle rysować te obszary gdzie gracz widzi jakis efekt, pozostawiajac reszte...

Dzięki temu kodowi powinniście już mieć własne światła tam gdzie być powinny :}

Rysujemy swiatła za pomocą drawlights(tablica_ze_swiatłami,model,bzdury...);

Na koniec arta dam wam kod (rekord) modelu tglarraselectionmodel, może i jest troche tam zmiennych ale wszystkie się przydają do silnika 3D (pomoże wam to zrozumieć istotę budowania silnika) i będzie ich jeszcze więcej, ale macie na razie tyle:

type tglArraySelectionModel=record
VBO_V                : array of t3dpoint;
VBO_N                : array of t3dpoint;
VBO_T                : array of textpoint;
VBO_LIGHTT           : array of textpoint;
VBO_FACE_INFO                   : array of tvbofacenfo;  // start index i end index


USESVBO                         : boolean; //if usesvbo then rysujemy z vbo :}
vnormalarr                       : array of array of t3dpoint;
modelLIGHTMAPPED                : boolean;
modelSHADOWMAPPED               : boolean;
header                          : tArraySelectionFileHeader;
rotatebox                       : trotatebox;
FACE_IS_BUMPMAPPED              : array of boolean;
FACE_BUMPMAPPTEX                : array of gluint;      // <------ TO TRZEBA ZALADOWAC omg
FACE_BUMP_AMOUNT                : array of integer;
//FACE_TEXTURE_NFO                : array of texture_nfo;
// TO TYLKO DLA SWIATEL STATYCZNYCH (TYCH LIGHTMAP)
FACE_ISLIGHTED                  : array of boolean; //jak face jest w promieniu swiatla to dajemy true i nie jest przykryty
FACE_ISLIGHTED_INDEX            : array of array of integer; //indeks w tablicy drawlights([ lista swiatel ] )
                                 //pierwszy array to numer facea, drugi to numery swiatel
Face_CENTER                     : array of t3dpoint;
Face_DISTANCE                   : array of single;
Face_DISTANCE_INDEX             : array of single;
FLAG_FACES_FROM_FILE            : boolean; //z pliku skryptu bedzie to dzialac
FACE_NORMAL                     : array of t3dpoint;
FACE_VOLUME                     : array of FACE_VOLUME_ARRAY;      //collision VOLUME (POLYGON EDGE PLANES)
//Wygladac to bedzie tak:       <-- teraz nie wiem o co chdozi :X
//      face(numer)
//      {
//      cmds: setflag(num); //for flag other like blend are for bglcmd scritps
//      setbump(amount, texture filename); //sciezka do tekstury bumpmappowanej tej heightmap'y
//      }


FACE_FLAG                       : array of byte; //0-normal, 1-blend, 2 - do not draw, 3 - sky, 4 - light
OBJ_NUM                         : integer;
OBIEKTY                         : array of tarray_object;
facelength                      : array of integer;
face                            : array of tngasface;
TEXCOORDARRAYS                  : array of tngastexcoord;
COLARRAYS                       : array of array of t3dpoint;
EDGE_CLIP_normal                : array of array of t3dpoint;
EDGE_CLIP_distance              : array of array of single;
TEXARRAYS                       : array of array of textpoint;
LIGHTARRAYS                     : array of array of textpoint;  //koordynaty lightmap
SHADOWARRAYS                    : array of array of textpoint;  //koordynaty shadowmap
LIGHTINDEX                      : array of integer;             //numer lightmapy do uzycia przez sciane (face) z lightmap_textures
SHADOWINDEX                     : array of integer;
BLEND_TEXTURE_FACE              : array of array of array of text3dpoint; // array of array[0..127, 0..127] of text3dpoint;  // Texture data
BLEND_TEXTURE_FACEhandle        : array of tBLEND_TEXTURE_FACEhandle;
samevertex                      : array of array of array of integer;
arrays                          : array of
                                        array of tinasmcoord;
collisionmap                    : array of array of tngascollisionmap;
shaders                         : array of array[0..1] of gluint; //This is an array of gllist  0 = przed,  1 = po  [BGLCMD Scripting definitions]
face_uses_shader                : array of boolean;
face_types                      : array of tngasface_type;
vis_vertex                      : array of tcollision_vert;
//lightmap_luxel                  : array of tngas_lightmap_face;
textures                        : array of gluint;
textureisbumpmapped             : array of boolean; //true tylko wtedy kiedy jest bump mapa
light_textures                  : array of gluint;    //LIGHTMAP TEXTURES
Shadow_textures                 : array of gluint;
//lights                          : array of tngaslight;
ShadowMatrix                    : array of Array[0..15] of glFloat;

AMBIENT                         : t3dpoint;
CENTER                          : t3dpoint;
texture                         : gluint;
loadedtex                       : boolean;
maxx,minx                       : single;
maxy,miny                       : single;
maxz,minz                       : single;
isother                         : byte;
first_pass_render_arg           : text4dpoint;      //r,g,b,a
PORTAL_FILE                     : TPVS_FILE;
//INNE WAZNE!!!!
GROUP_FACES                     : BOOLEAN; //default false
GROUP_FACE_INDEX                : array of byte; //max 256 groups
translate                       : t3dpoint;
rotate                          : t4dpoint;
LIGHT_FILE                      : tLIGHTMAP_FILE;
SHADOW_FILE                     : tLIGHTMAP_FILE;
STATIC_LIGHT_FACES              : array of INTARRAY;
STATIC_LIGHT_CALCULATED         : BOOLEAN;
DRAW_OLDSTYLE_NORMAL            : boolean;
DRAW_SHADOW_VOLUME              : BOOLEAN;
BASE_SHADOW_VOLUME              : tfacearray
end;

22 komentarzy

cien nie leci, cien jest rzucany:) jak to nie ma cieni ? na jednym screeni pokazales :) Zreszta niewazne:) Pozdr. skalniak

One sa rysowane na stencil bufferze, nie ma nic to wspolnego z cieniami wolumetrycznymi czy czyms takim, a cien jest tylko na drugim rysunku od góry pokazany nigdzie wiecej, reszta to sprawa OpenGL Lighting GL_LIGHT0 i te sprawy :P
W sumie GeForce 4 to chyba obsluguje bo na GF3 nie testowałem, to chodzi o te inicjacje rozszerzeń karty żeby wszystko poprawnie działało... kurde no musze sie nauczyc programowo tworzyc cienie...

ok z kodu wywnioskowalem ze to chyba jednak cienie wolumetryczne:)

GF6600 to dosc duze wymagania jak na taka grafike. Napisales
Nie czytalem calego ale...
"Małe objaśnienie: światło punktowe to trójwymiarowa tektura nałożona na obiekt!" - to chyba tylko daje zanik wraz z odlegloscia a nie pelne oswietlenie. Interesuje mnie czy cienie na tych screenach sa wykonane technika cieni wolumetrycznych ?

aaa nie wiem ja tu tylko sprzatam :/

Właśnie teraz zauważyłem, że to rekord, a nie klasa - wzorowałem się na tym, co napisałeś w tekście, nie patrząc na kod. To jeszcze spytam, po co nazywać coś czymś, czym to nie jest? :>

a wy uzywacie takich nazw ze nie wiadomo o co wam chodzi, a ta klasa to jest rekord

"NIe muszy chyba mówić, że gdy stworzymy sobie klase tswiatlo ktora ..."

A jeszcze niedawno twierdziłeś, że OOP w grach jest nieprzydatne i do dupy...

pozmieniasz typy i zmienne musizs dodac obsluge tablic, instrukcje opengl przepisujesz, zmieniasz skladnie, a drawglarrayselection(model); to tylko (btw draw_only_alpha_faces i swiatla sa potrzebne do bumpmappingu ale w tym przypadku [ormalnego rysowania] nie potrzebne

procedure DrawglArraySelection(Model : tglArraySelectionModel;draw_only_alpha_faces : boolean; swiatla : array of tnoxx_gllight; viev_pos : t3dpoint); overload;
var
i,j,n : integer; // x cos / y sin
FACECENTERPOINT : t3dpoint;
faceb : boolean;
begin

if model.loadedtex = true then glbindtexture(GL_TEXTURE_2D,model.texture);

if model.USESVBO then begin
glVertexPointer(3, GL_FLOAT, sizeof(t3dpoint), @model.VBO_V[0]);
glNormalPointer(GL_FLOAT, sizeof(t3dpoint),@model.VBO_N[0]);
// glNormalPointer(2, GL_FLOAT, sizeof(t3dpoint),@model.VBO_N[0]);
// glColorPointer(2, GL_FLOAT, sizeof(t3dpoint),@model.VBO_N[0]);
glTexCoordPointer(2, GL_FLOAT, sizeof(textpoint),@model.VBO_T[0]);

for i:=0 to high(model.face) do
begin
if length(model.textures) > 0 then glbindtexture(GL_TEXTURE_2D,model.textures[model.face[i].textureindex]);
glDrawArrays(GL_TRIANGLE_FAN, model.VBO_FACE_INFO[i].INDEX_START , model.VBO_FACE_INFO[i].length);

end;

exit;
end;

for i:=0 to high(model.face) do
begin

faceb:=false;
if length(model.textures) > 0 then glbindtexture(GL_TEXTURE_2D,model.textures[model.face[i].textureindex]);

if draw_only_alpha_faces then
if model.FACE_FLAG[i] = 2 then begin
glenable(GL_BLEND);
faceb:=true;glBlendFunc( GL_SRC_ALPHA, GL_ONE);
drawface(model,zeropoint,i);
gldisable(GL_BLEND);
glblendfunc(GL_ONE,GL_ONE);
end; // koniec if draw_only_alpha_faces

//jak bump to rysuj same
{if model.textureisbumpmapped[model.face[i].textureindex] = true then begin
model.FACE_IS_BUMPMAPPED[i] := true;
DrawblendBUMPMAPonFace(model,model.FACE_BUMPMAPPTEX[i],model.textures[model.face[i].textureindex],i,swiatla[0],
4000);

end; }

if not draw_only_alpha_faces then
if model.FACE_IS_BUMPMAPPED[i] = false then
begin
//glcolor3f(0.1,0.1,0.1);

if length(model.textures) > 0 then glbindtexture(GL_TEXTURE_2D,model.textures[model.face[i].textureindex]);
//glBlendFunc(GL_ONE, GL_ZERO);
// glBlendFunc(GL_DST_COLOR, GL_ZERO);
drawface(model,viev_pos,i);

      {

if model.modelLIGHTMAPPED then begin
//glBlendFunc(GL_DST_COLOR, GL_ZERO);
glbindtexture(GL_TEXTURE_2D,model.light_textures[model.LIGHTINDEX[i]]);
drawLIGHTFACE(model.face[i],model.arrays[i],model.lightarrays[i],viev_pos); end; }

end;
end;

if IDRAWROTATEDMODEL then begin glpopmatrix(); IDRAWROTATEDMODEL := false; end;

end;

Jeszcze nie czytalem tego arta ale moze sie zabiore tylko ze zrodla sa w jakims pascalu jezeli dobrze widze(?) to tak srednio z przekladem tego na cpp. Tak wiem nie jest to trudne ale czasochlonne... choc moze przez to lepiej sie utrwala wiadomosci nabyte w arcie ;P

Komórkowy: wklej ten tekst do Worda albo zainwestuj w Firefoksa 2.0 - sprawdza poprawność pisowni.
Co do obrazków, to zamiast nazywać je "DYNAMICZNY_CIEN2007-04-01abc.jpg", nazwij np.: "OpenGL-dynamiczny-cien.jpg". Zdjęcia dodasz w zakładce "Załączniki" w edycji artykułu, a zamieścisz w odpowiednim miejscu poprzez:

nazwa_pliku.jpg - wyświetli obrazek
Dynamiczny cień - wstawi link

To moze przeczytaj co jest pod linkami

Fajny artykuj, tylko go przegladnolem bo narazie nieznam nawet podstaw OpenGL :p

To nazwij je SENSOWNIE i dodaj do artykułu jako załączniki.
Ale SENSOWNIE! Pamiętaj, że nazwy plików są unikalne dla całego serwisu - nie tylko dla jednego artykułu.

Wytlumacz mi to :0 ladnie prosze :J

Pozdrów Irenkę
PS: Zwazaj na bledy ortograficzne
PS2: Wrzuc obrazki np na imidzhaka i juz, tam nie ma zabezpieczen takich jak na host.sk

<ort>sproboje</ort> sie poprawic, co do linków a gdzie wpisujesz adres strony ? bo to trzeba tam skopiowac i nacisnąc ENTER

Komórkowy, zrób coś z kodem źródłowym. Poprawiłbym formatowanie (wcięcia etc.), ale to nie mój bałagan. Co do linków. Kopiuje się gdzie :|

Na linki sie nie klika tylko <ort>kopjuje</ort>, i czy kiedys wam dzialal jakis link z <ort>artykolów</ort> bo mi nie! zawsze jak klikałem przechodziło do <ort>jakijś</ort> tam nieistniejącej strony na 4programmers.net wiec o co <ort>chosi</ort>

Popraw interpunkcję, linki (vide komentarz poniżej), oraz "CZY TO MUSZĄ BYĆ WERSALIKI W TYTULE?"

Te linki na początku artu nie działają

To nazwij je SENSOWNIE i dodaj do artykułu jako załączniki.
Ale SENSOWNIE! Pamiętaj, że nazwy plików są unikalne dla całego serwisu - nie tylko dla jednego artykułu.

:]

  1. :]
  2. szczerze to bym wolał, aby te zdjęcia były na 4p nie na imageshack, ani na moim serwerze bo z imghack to mi to i tak kiedyś tam usuną, z host.sk nie