2012-09-23 18 views
6

Ja koduję jako tutorzy NeHe Lekcja 27 powiedziała mi, ale jest to algorytm z-pass. Kiedy jestem w cieniu, cień zniknął. Ktoś powiedział mi, że mogę użyć algorytmu z-fail, aby rozwiązać ten problem. , więc spędzam dwa dni na badanie algorytmu z-fail. Na koniec nie mogę tego rozgryźć. Mój program nigdy nie działa tak, jak sądzę.jak zrealizować algorytm Z-Fail w OpenGL?

Algorytm z-nie jak wiki wymienione:

Głębokość nie Około roku 2000, kilka ludzie odkryli, że metoda HEIDMANN może być wykonane do pracy na wszystkich pozycjach kamer poprzez odwrócenie głębi. Zamiast zliczać powierzchnie cienia przed powierzchnią obiektu, powierzchnie za nim można liczyć równie łatwo, z tym samym efektem końcowym. To rozwiązuje problem oka będącego w cieniu, ponieważ cienie między okiem a obiektem nie są zliczane, ale wprowadza warunek, że tylny koniec objętości cienia musi zostać pokryty, lub cienie będą kończyły się brakiem tam, gdzie punkty objętości wstecz do nieskończoności.

  1. Wyłącz zapisy do buforów głębi i kolorów.

  2. Użyj ubioru twarzowego.

  3. Ustaw operację szablonu na przyrost na głębokości niepowodzenie (tylko policz cienie za obiektem).

  4. Renderowanie objętości cienia.

  5. Użyj uśpienia twarzy.

  6. Ustawić operację szablonu na dekrement na głębokości niepowodzenie.

  7. Renderowanie objętości cienia.

Główne pytanie uważam za test głębi. W kroku 3 i 6 operacja szablonu jest oparta na niepowodzeniu głębokości. Chociaż może pokazywać cień, ale może być zacieniony na obiekcie przed nim (tzn. Obiekt, którego wartość bufora głębi jest mniejsza niż). efekt cienia wygląda bałagan.

Jednak w algorytmie z-pass operacja szablonowa oparta jest na przejściu głębokościowym, co oznacza, że ​​może nie tylko pokazywać cień, ale także cienie na obiekcie znajdującym się za nim, co jest zgodne z systemem oka.

, więc jak rozwiązać ten problem, aby mój algorytm głębokości błędu pokazał cień na odpowiednich obiektach.

tutaj jest mój oo upaść kod algorytm (gdzieś może być gdzie, proszę mi pomóc dowiedzieć się, efekt cienia jest okropne)

VECTOR vec;   
void shadowvolume(SECTOR &sec,float *lp) 
{ 
    unsigned int p1, p2; 
    VECTOR   v1, v2; 
    int i, j, k, jj; 
    for (i=0; i<sec.numplanes;i++) 
    { 
     if (sec.planes[i].visible) 
     { 
      for (j=0;j<3;j++) 
      { 
       k = sec.planes[i].neigh[j]; 
       if ((!k) || (!sec.planes[k-1].visible))//如果以第k个点开始的邻边没有相邻平面或者相邻平面不可见 
       { 
        // here we have an edge, we must draw a polygon 
        p1 = sec.planes[i].p[j]-1;//邻边的起点 
        jj = (j+1)%3;   
        p2 = sec.planes[i].p[jj]-1;//邻边的终点 

        //calculate the length of the vector 
        v1.x = (sec.points[p1].vec.x - lp[0])*100; 
        v1.y = (sec.points[p1].vec.y - lp[1])*100; 
        v1.z = (sec.points[p1].vec.z - lp[2])*100; 

        v2.x = (sec.points[p2].vec.x - lp[0])*100; 
        v2.y = (sec.points[p2].vec.y - lp[1])*100; 
        v2.z = (sec.points[p2].vec.z - lp[2])*100; 

        glBegin(GL_TRIANGLE_STRIP);//将光源连到邻边的起点并延长,将光源连到邻边的终点的并延长,最后延长出来的梯形,画了过后模板缓冲区的值加1 
        glVertex3f(sec.points[p1].vec.x,sec.points[p1].vec.y,sec.points[p1].vec.z); 
        glVertex3f(sec.points[p1].vec.x + v1.x,sec.points[p1].vec.y + v1.y,sec.points[p1].vec.z + v1.z); 
        glVertex3f(sec.points[p2].vec.x,sec.points[p2].vec.y,sec.points[p2].vec.z); 
        glVertex3f(sec.points[p2].vec.x + v2.x,sec.points[p2].vec.y + v2.y,sec.points[p2].vec.z + v2.z); 
        glEnd(); 
       } 
      } 
      // caps 
      glBegin(GL_TRIANGLES); 
      for(k=0;k<3;k++) 
       glVertex3fv((float*)&sec.points[sec.planes[i].p[k]-1].vec); 
      glEnd(); 
      glBegin(GL_TRIANGLES); 

      for(k=2;k>=0;k--) 
      { 
       vec.x=sec.points[sec.planes[i].p[k]-1].vec.x+(sec.points[sec.planes[i].p[k]-1].vec.x-lp[0])*100; 
       vec.y=sec.points[sec.planes[i].p[k]-1].vec.y+(sec.points[sec.planes[i].p[k]-1].vec.y-lp[1])*100; 
       vec.z=sec.points[sec.planes[i].p[k]-1].vec.z+(sec.points[sec.planes[i].p[k]-1].vec.z-lp[2])*100; 
       glVertex3fv((float*)&vec); 
      } 
      glEnd(); 

     } 
    } 



} 
void CastShadow(SECTOR &sec, float *lp) 
{//lp是光源相对于物体的位置 
    float   side; 

    glEnable(GL_CULL_FACE); 
    int i; 
    for (i=0;i<sec.numplanes;i++) 
    { 
     side =sec.planes[i].planeeq.a*lp[0]+sec.planes[i].planeeq.b*lp[1]+sec.planes[i].planeeq.c*lp[2]+sec.planes[i].planeeq.d*lp[3]; 
     if (side>0) 
      sec.planes[i].visible = TRUE; 
     else 
      sec.planes[i].visible = FALSE; 
    } 

    glDisable(GL_LIGHTING); 
    glDepthMask(GL_FALSE); 
    glDepthFunc(GL_LEQUAL); 
    glEnable(GL_STENCIL_TEST); 
    glColorMask(0, 0, 0, 0); 
    glStencilFunc(GL_ALWAYS, 0, 0xffffffff); 

    glCullFace(GL_FRONT); 
    glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); 
    //glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); 
    shadowvolume(sec,lp); 

    glCullFace(GL_BACK); 
    glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); 
    //glStencilOp(GL_KEEP,GL_KEEP, GL_INCR); 
    shadowvolume(sec,lp); 



    glColorMask(1, 1, 1, 1); 

    //draw a shadowing rectangle covering the entire screen 
    glColor4f(0.0f, 0.0f, 0.0f,0.4f); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff); 
    //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 
    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 
    glPushMatrix(); 
    glLoadIdentity(); 
    glBegin(GL_TRIANGLE_STRIP); 
     glVertex3f(-0.1f, 0.1f,-0.0010f); 
     glVertex3f(-0.1f,-0.1f,-0.0010f); 
     glVertex3f(0.1f, 0.1f,-0.0010f); 
     glVertex3f(0.1f,-0.1f,-0.0010f); 
    glEnd(); 
    glPopMatrix(); 
    glDisable(GL_BLEND); 

    glDepthFunc(GL_LEQUAL); 
    glDepthMask(GL_TRUE); 
    glEnable(GL_LIGHTING); 
    glDisable(GL_STENCIL_TEST); 
    glShadeModel(GL_SMOOTH); 
    glDisable(GL_CULL_FACE); 
} 

klasa Vector jest tak:

class VECTOR 
{ 
public: 
    float x,y,z; 
    bool operator==(VECTOR vec) 
    { 
     if(x==vec.x && y==vec.y && z==vec.z) 
      return true; 
     return false; 
    } 
}; 

klasa sektora i inni jest tak:

class PLANEEQ 
{ 
public: 
    float a,b,c,d; 
}; 
class PLANE 
{ 
public: 
    unsigned int p[3];//点的序号 
    VECTOR normal[3]; 
    unsigned int neigh[3];//平面3个相依平面的序号 
    PLANEEQ planeeq; 
    bool visible; 
    PLANE() 
    { 
     neigh[0]=0; 
     neigh[1]=0; 
     neigh[2]=0; 
     planeeq.a=0; 
     planeeq.b=0; 
     planeeq.c=0; 
     planeeq.d=0; 
     visible=false; 
    } 
}; 

class SECTOR 
{ 
public: 
    int numpoints; 
    int numplanes; 
    vector<VERTEX> points; 
    vector<PLANE> planes; 
    MATERIAL material; 
    bool read(); 
    bool loadtexture(); 
    bool build(); 
    bool plane_calc(); 
    void SetConnectivity(); 
    SECTOR& SECTOR::subdivide(long depth); 
    SECTOR(string str1,string str2):modelfilename(str1),texturefilename(str2) 
    { 
     numpoints=0; 
     numplanes=0; 

    } 
    SECTOR() 
    { 
     numpoints=0; 
     numplanes=0; 

    } 

private: 
    FILE *modelfilein,*texturefilein; 
    string modelfilename,texturefilename; 
    char oneline[255]; 
    UINT texturename; 
    AUX_RGBImageRec *TextureImage; 
}; 
class POSITION 
{ 
public: 
    float x,y,z,w; 
}; 

funkcja DrawGLScene w moim głównym.CPP jest tak:

int DrawGLScene(GLvoid)         
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |GL_STENCIL_BUFFER_BIT); 
    glLoadIdentity(); 
    DrawGLRoom(); 
    glLoadIdentity(); 
    GLfloat xtrans = -xpos; 
    GLfloat ztrans = -zpos; 
    GLfloat ytrans = -ypos-1.2f; 
    GLfloat sceneroty = 360.0f - yrot; 

    glRotatef(lookupdown,1.0f,0,0); 
    glRotatef(sceneroty,0,1.0f,0); 
    glTranslatef(xtrans, ytrans, ztrans); 
    brick_sec.build(); 
    floor_sec.build(); 
    //wall_sec.build(); 

    //CastShadow(wall_sec,(float *)&lightgroup.lights[0].pos); 
    CastShadow(brick_sec,(float*)&lightgroup.lights[0].pos); 
    CastShadow(floor_sec,(float*)&lightgroup.lights[0].pos);  


    lightgroup.build(); 
    glColor4f(0.7f, 0.4f, 0.0f, 1.0f); 
    glDisable(GL_LIGHTING);        
    glDepthMask(GL_FALSE);        
    glTranslatef(lightgroup.lights[0].pos.x, lightgroup.lights[0].pos.y, lightgroup.lights[0].pos.z);    
    gluSphere(q, 0.2f, 16, 8); 
    glEnable(GL_LIGHTING); 
    glDepthMask(GL_TRUE); 
    if(space_time>0) 
    { 
     ypos=sin(space_time*3.1415926/180); 
     space_time-=4; 
    } 
    else 
    { 
     sp=false; 
    } 
    //glFlush(); 
    return TRUE;          // Everything Went OK 
} 

Ponieważ moja reputacja jest poniżej 10, nie mogę uchwycić efekt cienia, aby pokazać u jak źle to wygląda! pls pomóżcie mi, chciałbym, żebyś dla uwaga i ur czasu!

thx Najzero za przyznanie mi 5 punktów reputacji, teraz mogę przechwycić ekran, aby pokazać efekt. Dołączę szczegółowy opis.

z-karnet efekt algorytm: kiedy nie jestem w efekcie, to ok (pomarańczowy pot reprezentować światło) enter image description here

ale kiedy jestem w wall_shadow, to nie jest w porządku Cień muru zniknął, chociaż ceglany cień nadal tam jest.

enter image description here

więc muszę algorytm Z upaść, aby rozwiązać ten problem.but ostatni efekt mojego kodu realizowany jest tak: enter image description here kleszcz stanowią efekt cienia ma rację, krzyż reprezentuje shouldn cień pojawi się na obiekcie.

kolejny zrzut ekranu, enter image description here

+0

o to powinno być interesujące. Mieliśmy ogromny problem z podobnym problemem. Do czego jest ustawiony twój najbliższy samolot? nie widzę wywołania gluPerspective(), aby zgadnąć. Gdy zbliżająca się płaszczyzna wynosi 0, daje to szalone wyniki dla wszystkiego z renderowaniem Z zaangażowanym – Najzero

+0

oto moja funkcja gluPerspective: moja bliska płaszczyzna ustawiona na 0,001f gluPerspektyw (45.0f, (GLfloat) szerokość/(GLfloat) wysokość, 0,001f, 100,0 fa); nearplane nie może być 0, możesz zamiast tego użyć 0.00001. – nomorefancy

+0

Ten kod jest strasznie przestarzały. –

Odpowiedz

2

HA wreszcie znajdę problem w moich code.I jestem tak zadowolony, lol !!!!!!!!!

problemem jest gluPerspective (45.0f, (GLfloat) width/(GLfloat) height, 0.001f, 100.0f);

jak GuentherKrass powiedział w http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes

Jeśli zrobisz to w ten sposób, należy użyć macierzy projekcji perspektywa z nieskończonej dalekiej płaszczyzny lub użyj GL_DEPTH_CLAMP uniknąć zatyczkę są wycofywane przez płaszczyznę daleko wycinek .

więc wystarczy zmienić kod wyżej

gluPerspective (45.0f (GLfloat) Szerokość/(GLfloat) wysokość 0.001f, 1000000.0f);

porządku, to wygląda jak idealny !!!!!!!!!!!!!!!!! 111 hahahahaaa

dwa dni, zatrzymać się, bóg natychmiastowy noodles..it cholernie więc warto !!

ok ,, położę ostatni effct obraz out.If ktoś chce mojego kodu po prostu napisz do mnie ([email protected])

enter image description here enter image description here enter image description here enter image description here

czujność: się Ceglany cień jest niezależny od cienia ściany.

+1

haha ​​lol, szczęśliwy dla ciebie – Najzero