opengl: почему тень исчезает, когда я стою в тени?

если я не стою в тени, эффект тени выглядит идеально. но когда я в тени, тень исчезает. не знаю, почему?

вот мой код для реализации эффекта тени.

void  CastShadow(SECTOR &sec, float *lp)
{//lp is the relative position to the sec
    unsigned int    i, j, k, jj;
    unsigned int    p1, p2;
    VECTOR          v1, v2;
    float           side;


    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, 1, 0xffffffff);

    // first pass, stencil operation decreases stencil value
    glFrontFace(GL_CCW);
    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
    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();
                }
            }
    }

    // second pass, stencil operation increases stencil value
    glFrontFace(GL_CW);//这句表示画的多边形,只看到里面
    glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
    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();
                }
            }
    }

    glFrontFace(GL_CCW);
    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);
    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);

}

а класс SECTOR выглядит так:

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

person nomorefancy    schedule 21.09.2012    source источник


Ответы (1)


Поскольку вы уже обрабатывали «закрытие» теневого объема в ближней плоскости отсечения, у вас, вероятно, возникла проблема с камерой, находящейся внутри теневого объема, отбрасываемого объектом, находящимся за камерой. Вы можете проверить это, переместив камеру так, чтобы она находилась внутри теневого объема (там, где возникает проблема), а затем поверните камеру так, чтобы объект находился перед ближней плоскостью отсечения.

Для обработки таких особых случаев проще использовать алгоритм «ошибка глубины», хотя вы должны иметь возможность вычислять и отображать ограничения для дальних концов теневых томов. Обзор различий между алгоритмами теневых томов можно найти в википедии.

person Alex Peck    schedule 21.09.2012
comment
спасибо, я понял. алгоритм, который я использовал, - это z-pass, который действительно существует для этой проблемы. Чтобы решить эту проблему, я могу использовать алгоритм z-fail, как мне сказали вики. - person nomorefancy; 21.09.2012