2012-09-23 5 views
6

私はNeHeの教師としてコードレッスン27に教えてくれましたが、それはzパスアルゴリズムです。私が影になっているとき、影は消えています。誰かが私にこの問題を解決するためにz-failアルゴリズムを使用できると教えてくれました。 私はz-failアルゴリズムを研究するのに2日間を費やしています。最後に、私はそれを理解することができません。OpenGLでz-failアルゴリズムを実現する方法は?

ウィキが記載されているようなアルゴリズムを、zは、失敗:

深さは、2000年ごろ に失敗し、いくつかの人々はHeidmannの方法は、深さを逆にすることによって、すべてのカメラ位置のために働くようにすることができることを発見しました。オブジェクトの表面の前にある影の表面を数えるのではなく、その後ろの表面を同じように簡単に数えることができます。これは、目とオブジェクトの間の影のボリュームがカウントされないため、影の中の目の問題を解決しますが、影のボリュームの後端にはキャップを付ける必要があります。無限に戻る。

  1. 深度バッファおよびカラーバッファへの書き込みを無効にします。

  2. フロントフェイスカリングを使用してください。

  3. 深度に失敗するとステンシル操作を増分するように設定します(オブジェクトの後ろにカウントシャドウのみ)。

  4. シャドウボリュームをレンダリングします。

  5. バックカウリングを使用してください。

  6. 深度に失敗するとステンシル操作をデクリメントするように設定します。

  7. シャドウボリュームをレンダリングします。

私が思う主な質問は深度テストです。ステップ3と6では、ステンシル操作は深度フェイルに基づいています。しかし、それは影を表示することはできますが、前のオブジェクト(つまり、深度バッファ値がそれよりも小さいオブジェクト)影の効果が混乱して見える。

しかし、zパスアルゴリズムでは、ステンシル操作は深度パスに基づいているため、影を表示するだけでなく、後ろのオブジェクトに影を付けて、視覚系に対応していることを意味します。

この問題を解決するにはどのように私の深さのアルゴリズムを失敗させるアルゴリズムは、適切なオブジェクトの影を表示する。

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

は私のZ-失敗アルゴリズムのコードですVECTORクラスは、このようなものです

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

(どこどこ、私は見つける助けてくださいすることができ、シャドウ効果はひどいです)私のメインの中

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

DrawGLScene機能:

SECTORクラスと他の人がこのようなものです。CPPは、このようなものです:

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 
} 

私の評判は10の下にあるので、私はそれがどのように見えるかひどくUを表示するために影の効果をキャプチャすることはできません! plsは私を助け、私はあなたのために、あなたの気配りをしてくれるでしょう!

thx Najzeroが私に5の評判を与えてくれたので、今私は効果を示すために画面をキャプチャすることができます。私は詳細な説明を追記します。

のzパスアルゴリズムの効果: 私は有効ではないよとき、それは大丈夫だ(オレンジポットが光を表す) enter image description here

が、私はwall_shadowにいるとき、それは大丈夫ではありません! wall_shadowは消えましたが、brick_shadowはまだそこにあります。

enter image description here

ので、私はこれが最後の効果私のコードは、実現をproblem.but解決するためのz-失敗したアルゴリズムを必要とするこのようなものです:シャドウ効果が正しい表す enter image description here ダニ、クロスシャドウshouldnを表しますオブジェクトには表示されません。

別のスクリーンショット、 enter image description here

+0

これは面白いはずです。私たちは同じような問題を抱えています。あなたのnearplaneは何に設定されていますか? gluPerspective()呼び出しを見て、推測をしないでください。ニアプレーンが0の場合、Zレンダリングが含まれているものはすべて狂った結果になります – Najzero

+0

ここでは私のgluPerspective関数です:near near plane 0.001f gluPerspective(45.0f、(GLfloat)width /(GLfloat)height、0.001f、100.0 f); ニアプレーンを0にすることはできません。代わりに0.00001を使用することができます。 – nomorefancy

+0

このコードは大いに廃止されました。 –

答えて

2

ヘクタール、最後に、私はとても幸せです、私のcode.Iで問題を見つけ、笑!!!!!!!!!

問題はgluPerspective(45.0f、(GLfloat)width /(GLfloat)height、0.001f、100.0f)です。

GuentherKrassは、あなたがこのようにそれを行う場合http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes

に言ったように、ファークリッピング平面によって淘汰されているバックキャップを避けるために、無限遠く平面と透視投影行列を使用するか、GL_DEPTH_CLAMPを使用してください。

私はちょうど

gluPerspectiveなので(45.0f、(GLfloat)幅/(GLfloat)高さ、0.001f、1000000.0f)に上記のコードを変更します。

大丈夫、それは111 haha​​hahaaa

2日!!!!!!!!!!!!!!!!!完璧なように見える、インスタントnoodles..itの神がそうする価値畜生、起きて! :

OK ,,私は誰out.If最後effct絵は私のコードがちょうど([email protected]

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

注意を私にメールしたい置きますレンガの影は壁の影とは独立しています。

+1

笑、あなたのために幸せ – Najzero

関連する問題