2012-09-23 45 views
6

código como los tutores NeHe Lesson27 me dijeron, pero es un algoritmo z-pass. Cuando estoy en la sombra, la sombra se ha ido. Alguien me dijo que puedo usar el algoritmo z-fail para resolver este problema. así que me paso dos días para investigar el algoritmo z-fail. Por último, no lo puedo entender. Mi programa nunca funciona como creo.cómo realizar el algoritmo z-fail en opengl?

El algoritmo z fallar como el wiki de la lista:

Profundidad fallar Alrededor del año 2000, varias personas descubrieron que el método de Heidmann puede hacerse funcionar para todas las posiciones de la cámara mediante la inversión de la profundidad. En lugar de contar las superficies de sombra en frente de la superficie del objeto, las superficies detrás de él se pueden contar con la misma facilidad, con el mismo resultado final. Esto resuelve el problema del ojo en la sombra, ya que los volúmenes de sombra entre el ojo y el objeto no se cuentan, pero introduce la condición de que el extremo posterior del volumen de sombra debe estar tapado, o las sombras terminarán desaparecidas donde los puntos de volumen hacia atrás hasta el infinito.

  1. Desactiva las escrituras en los búferes de profundidad y color.

  2. Utilice la eliminación frontal.

  3. Establezca la operación de la galería de símbolos para aumentar el error de profundidad (solo cuente las sombras detrás del objeto).

  4. Renderizar los volúmenes ocultos.

  5. Utilice la eliminación de imágenes ocultas.

  6. Establezca el funcionamiento de la galería de símbolos para disminuir el error de profundidad.

  7. Renderizar los volúmenes ocultos.

La pregunta principal, creo que es la prueba de profundidad. En los pasos 3 y 6, la operación de estarcido se basa en la falla de profundidad. Aunque puede mostrar la sombra, pero puede oscurecerse sobre el objeto que tiene delante (es decir, el objeto cuyo valor de memoria intermedia de profundidad es menor). efecto de sombra parece desorden.

Pero en el algoritmo z-pass, la operación del estarcido se basa en el paso de profundidad, lo que significa que no solo puede mostrar la sombra, sino también el objeto detrás de ella, de acuerdo con el sistema ocular.

Así que cómo resolver este problema para que mi algoritmo de falla de profundidad muestre la sombra en los objetos correctos.

aquí es mi código de algoritmo z-fail (en algún lugar puede ser que, por favor, ayúdame a encontrar a cabo, el efecto de sombra es horrible)

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

la clase Vector es así:

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

la clase SECTOR y otros es la siguiente:

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

la función DrawGLScene en mi principal.CPP es así:

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 
} 

Desde mi reputación está por debajo de 10, que no se pueden capturar el efecto de sombra para mostrar u lo mal que parece! pls ayúdenme, ¡¡¡lo haría por su atención y su hora !!!

th Najzero por darme 5 reputación, ahora puedo capturar la pantalla para mostrar el efecto. Voy a anexar una descripción detallada a continuación.

el efecto algoritmo de paso z: cuando no estoy en el efecto, está bien (el bote de color naranja representan la luz) enter image description here

pero cuando estoy en el wall_shadow, no está bien ! wall_shadow se ha ido, aunque brick_shadow todavía está allí.

enter image description here

así que necesito z quebrar algoritmo para resolver este problem.but el último efecto se dio cuenta de mi código es así: enter image description here la garrapata representan el efecto de sombra es correcto, la cruz representa la sombra shouldn no aparece en el objeto.

otra captura de pantalla, enter image description here

+0

oh, esto debería ser interesante. Tuvimos un gran problema con un problema similar. ¿Cuál es tu plano cercano establecido? no veo una llamada a gluPerspective() para adivinar. Cuando el plano cercano es 0 obtiene algunos resultados extravagantes para todo con la representación Z implicada – Najzero

+0

aquí está mi función gluPerspective: mi plano cercano configurado en 0.001f gluPerspective (45.0f, (GLfloat) width/(GLfloat) height, 0.001f, 100.0 F); el plano cercano no puede ser 0, puede usar 0.00001 en su lugar. – nomorefancy

+0

Este código está terriblemente en desuso. –

Respuesta

2

una hectárea, por fin, creo que el problema en mis code.I soy tan feliz, lol !!!!!!!!!

el problema es gluPerspective (45.0f, (GLfloat) width/(GLfloat) height, 0.001f, 100.0f);

como dijo el GuentherKrass en el http://www.opengl.org/discussion_boards/showthread.php/146157-Z-Fail-Stencil-Shadow-Volumes

Si lo haces de esta manera, asegúrese de usar una matriz de proyección en perspectiva con un plano lejano infinito o utilizar GL_DEPTH_CLAMP para evitar el tapón que se sacrificaron por el plano de delimitación lejano .

así que acaba de cambiar el código anterior para

gluPerspective (45.0f, (GLfloat) ancho/GLfloat) Altura (, 0.001f, 1000000.0f);

bien, Parece perfecta !!!!!!!!!!!!!!!!! 111 hahahahaaa

dos días, mantenerse, dios de noodles..it instantánea maldita por lo que vale la pena !!

bien ,, voy a poner la última imagen effct out.If alguien quiere mi código sólo me correo electrónico ([email protected])

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

atención: la la sombra de ladrillo es independiente de la sombra de la pared.

+1

jaja jajaja, feliz por ti – Najzero

Cuestiones relacionadas