2012-09-23 23 views
6

Tôi viết mã như những người dạy kèm NeHe Lesson27 nói với tôi, nhưng đó là một thuật toán z-pass. Khi tôi ở trong bóng tối, cái bóng đã biến mất. Ai đó nói với tôi rằng tôi có thể sử dụng thuật toán z-fail để giải quyết vấn đề này. vì vậy tôi dành hai ngày để nghiên cứu thuật toán z-fail. Cuối cùng, tôi không thể tìm ra nó. Chương trình của tôi không bao giờ chạy như những gì tôi nghĩ.làm thế nào để nhận ra thuật toán z-fail trong opengl?

Thuật toán z-thất bại như wiki liệt kê:

Depth thất bại Khoảng năm 2000, một số người phát hiện ra rằng phương pháp Heidmann có thể được thực hiện để làm việc cho tất cả các vị trí máy ảnh bằng cách đảo ngược chiều sâu. Thay vì đếm các bề mặt bóng ở phía trước bề mặt của vật thể, các bề mặt phía sau nó có thể được đếm một cách dễ dàng, với cùng một kết quả cuối cùng. Điều này giải quyết vấn đề của mắt trong bóng, vì khối lượng bóng giữa mắt và đối tượng không được tính, nhưng giới thiệu điều kiện rằng phần cuối của khối lượng bóng phải được giới hạn, hoặc bóng sẽ kết thúc ở nơi khối lượng điểm lạc hậu đến vô cùng.

  1. Tắt ghi vào độ sâu và bộ đệm màu.

  2. Sử dụng tách khuôn mặt trước.

  3. Đặt thao tác stencil để tăng độ sâu thất bại (chỉ đếm bóng phía sau đối tượng).

  4. Render khối lượng bóng.

  5. Sử dụng tách khuôn mặt.

  6. Đặt thao tác stencil để giảm độ sâu thất bại.

  7. Render khối lượng bóng.

Câu hỏi chính tôi nghĩ là thử nghiệm độ sâu. Ở bước 3 và 6, thao tác stencil dựa trên độ sâu thất bại. Mặc dù nó có thể hiển thị bóng, nhưng nó có thể bị che khuất trước đối tượng (ví dụ: đối tượng có giá trị buffer sâu nhỏ hơn nó). hiệu ứng đổ bóng trông rối rắm. Tuy nhiên, trong thuật toán z-pass, hoạt động stencil dựa trên độ sâu vượt qua, điều đó có nghĩa là nó không chỉ có thể hiển thị bóng, mà còn chỉ che khuất đối tượng phía sau nó, phù hợp với hệ thống mắt.

do đó, cách giải quyết vấn đề này để làm cho thuật toán lỗi chiều sâu của tôi hiển thị bóng trên đúng đối tượng.

đây là z-thất bại đang thuật toán của tôi (ở đâu đó có thể ở đâu, xin vui lòng giúp tôi tìm hiểu, các hiệu ứng đổ bóng là khủng khiếp)

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); 
} 

lớp VECTOR là như thế này:

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; 
    } 
}; 

lớp SECTOR và các trường khác giống như sau:

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; 
}; 

chức năng DrawGLScene trong chính.cpp là như thế này:

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 
} 

Kể từ khi danh tiếng của tôi là dưới 10 tuổi, tôi không thể nắm bắt được hiệu ứng đổ bóng để hiển thị u thế nào xấu nó trông giống như! pls giúp tôi, tôi sẽ thx u cho sự chú ý ur và thời gian ur !!!

thx Najzero cho tôi 5 danh tiếng, bây giờ tôi có thể chụp màn hình để hiển thị hiệu ứng. Tôi sẽ nối thêm mô tả chi tiết theo sau.

tác dụng thuật toán z-pass: khi tôi không có trong thực tế, nó là ok (nồi cam đại diện cho ánh sáng) enter image description here

nhưng khi tôi đang ở wall_shadow, nó không phải là ok các wall_shadow đã biến mất, mặc dù brick_shadow vẫn còn đó.

enter image description here

vì vậy tôi cần z-thất bại thuật toán để giải quyết việc này problem.but hiệu ứng cuối cùng mã của tôi nhận ra là như thế này: enter image description here các đánh dấu đại diện cho hiệu ứng đổ bóng là đúng, cây thập tự đại diện cho shouldn bóng không xuất hiện trên đối tượng.

ảnh chụp màn hình khác, enter image description here

+0

oh điều này phải thú vị. Chúng tôi đã có một vấn đề với một vấn đề tương tự. Bộ gần kề của bạn được đặt là gì? không thấy gluPerspective() gọi để đoán. Khi nearplane là 0 nó được một số kết quả điên cho tất cả mọi thứ với Z rendering tham gia – Najzero

+0

đây là gluPerspective chức năng của tôi: máy bay gần của tôi thiết lập để 0.001f gluPerspective (45.0f, (GLfloat) chiều rộng/(GLfloat) chiều cao, 0,001f, 100,0 f); máy đa năng không thể bằng 0, u có thể sử dụng 0,00001. – nomorefancy

+0

Mã này không được chấp nhận. –

Trả lời

2

một ha, Cuối cùng, tôi tìm thấy những vấn đề trong code.I tôi rất hạnh phúc, lol !!!!!!!!!

vấn đề là gluPerspective (chiều rộng 45,0f, (GLfloat)/(GLfloat), 0,001f, 100,0f);

như GuentherKrass nói trong http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes

Nếu bạn làm theo cách này, hãy chắc chắn sử dụng một ma trận chiếu quan điểm với một mặt phẳng xa vô hạn hoặc sử dụng GL_DEPTH_CLAMP để tránh nắp lại được chọn lọc bởi máy bay xa cắt .

vì vậy tôi chỉ cần thay đổi mã ở trên để

gluPerspective (45.0f, (GLfloat) chiều rộng/(GLfloat) chiều cao, 0.001f, 1000000.0f);

alright, Dường như hoàn hảo !!!!!!!!!!!!!!!!! 111 hahahahaaa

hai ngày, ở lại, thần noodles..it tức thời của chết tiệt như vậy giá trị !!

ok ,, tôi sẽ đưa hình ảnh effct cuối cùng out.If ai muốn mã của tôi chỉ gửi email cho tôi ([email protected])

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

chú ý: sự bóng gạch độc lập với bóng tường.

+1

haha ​​lol, vui cho bạn – Najzero

Các vấn đề liên quan