(OpenGL阴影贴图)在不正确的面上投射阴影

(OpenGL阴影贴图)在不正确的面上投射阴影,opengl,glsl,Opengl,Glsl,以下是演示图像: 左上256x256矩形是深度纹理 我在第一次使用平行投影渲染阴影贴图 然后在第二遍渲染场景 然后在最后一个过程中使用阴影贴图渲染场景 阴影有时渲染两次或在错误的曲面上渲染 有什么解决办法吗 完整代码如下: typedef struct { vec3_t org;//origin vec3_t off;//position offset vec3_t ang;//angle float dist;//radius int w;//def

以下是演示图像:

左上256x256矩形是深度纹理

我在第一次使用平行投影渲染阴影贴图

然后在第二遍渲染场景

然后在最后一个过程中使用阴影贴图渲染场景

阴影有时渲染两次或在错误的曲面上渲染

有什么解决办法吗

完整代码如下:

typedef struct
{
    vec3_t org;//origin
    vec3_t off;//position offset
    vec3_t ang;//angle
    float dist;//radius
    int w;//default 512
    int h;//default 512
    int depth;//depth texture
    int color;//color texture
    int dimension;//default = 8
    float mvmatrix[16];
    float projmatrix[16];
    cl_entity_t *followent;
    int inuse;
}sdlight_t;

void R_RenderDepthMap()
{
    qglPolygonOffset( 5.0, 0.0 );
    qglEnable(GL_POLYGON_OFFSET_FILL);

    if(cursdlight->followent)
    {
        VectorCopy(cursdlight->followent->origin, cursdlight->org);
    }

    qglMatrixMode(GL_PROJECTION);
    qglLoadIdentity();
    qglOrtho(-cursdlight->w / cursdlight->dimension, cursdlight->w / cursdlight->dimension, -cursdlight->h / cursdlight->dimension, cursdlight->h / cursdlight->dimension, -9999, 9999);//cursdlight->dist

    qglMatrixMode(GL_MODELVIEW);
    qglLoadIdentity();

    qglRotatef(-90, 1, 0, 0);
    qglRotatef(90, 0, 0, 1);
    qglRotatef(-cursdlight->ang[2], 1, 0, 0);
    qglRotatef(-cursdlight->ang[0], 0, 1, 0);
    qglRotatef(-cursdlight->ang[1], 0, 0, 1);
    qglTranslatef(-cursdlight->org[0], -cursdlight->org[1], -cursdlight->org[2]);

    qglViewport(0, 0, cursdlight->w, cursdlight->h);

    glGetFloatv(GL_PROJECTION_MATRIX, cursdlight->projmatrix);
    glGetFloatv(GL_MODELVIEW_MATRIX, cursdlight->mvmatrix);

    qglDepthRange(1.0, 0.0);
    qglDepthFunc(GL_LEQUAL);
    qglEnable(GL_CULL_FACE);
    //qglCullFace(GL_FRONT);
    qglClearColor(1, 1, 1, 1);
    qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Render Models..
    R_DrawEntitiesOnList();

    qglDisable(GL_POLYGON_OFFSET_FILL);
    qglBindFramebufferEXT(GL_READ_FRAMEBUFFER, s_BackBufferFBO.s_hBackBufferFBO);
    qglActiveTextureARB(GL_TEXTURE0);
    qglBindTexture(GL_TEXTURE_2D, cursdlight->depth);
    qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, cursdlight->w, cursdlight->h, 0);
}

void R_SetupShadowLight(void)
{
    // enable automatic texture coordinates generation
    GLfloat planeS[] = {1.0, 0.0, 0.0, 0.0};
    GLfloat planeT[] = {0.0, 1.0, 0.0, 0.0};
    GLfloat planeR[] = {0.0, 0.0, 1.0, 0.0};
    GLfloat planeQ[] = {0.0, 0.0, 0.0, 1.0};

    // setup texture stages
    qglActiveTextureARB(GL_TEXTURE0_ARB);
    qglBindTexture(GL_TEXTURE_2D, cursdlight->depth);

    qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_REF_TO_TEXTURE);
    qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
    qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY);

    qglEnable(GL_TEXTURE_GEN_S);
    qglEnable(GL_TEXTURE_GEN_T);
    qglEnable(GL_TEXTURE_GEN_R);
    qglEnable(GL_TEXTURE_GEN_Q);

    qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 
    qglTexGenfv(GL_S, GL_EYE_PLANE, planeS);
    qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 
    qglTexGenfv(GL_T, GL_EYE_PLANE, planeT);
    qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 
    qglTexGenfv(GL_R, GL_EYE_PLANE, planeR);
    qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); 
    qglTexGenfv(GL_Q, GL_EYE_PLANE, planeQ);

    // load texture projection matrix
    qglMatrixMode(GL_TEXTURE);
    qglLoadIdentity();

    qglTranslatef(0.5, 0.5, 0.5);
    qglScalef(0.5, 0.5, 0.5);
    qglMultMatrixf(cursdlight->projmatrix);
    qglMultMatrixf(cursdlight->mvmatrix);

    qglMatrixMode(GL_MODELVIEW);

    if (gl_polyoffset->value)
    {
        qglEnable(GL_POLYGON_OFFSET_FILL);
        qglPolygonOffset(-1, -gl_polyoffset->value);
    }

    qglDepthMask(GL_FALSE);
    qglEnable(GL_BLEND);
    qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
    qglColor4f(1,1,1,1);

    qglUseProgramObjectARB(shadow_program);
    qglUniform1iARB(shadow_uniform.shadowmap, 0);
}

void R_FinishShadowLight(void)
{
    qglUseProgramObjectARB(0);

    if (gl_polyoffset->value)
    {
        qglDisable(GL_POLYGON_OFFSET_FILL);
    }
    qglDepthMask(GL_TRUE);
    qglDisable(GL_BLEND);

    qglActiveTextureARB(GL_TEXTURE0_ARB);

    qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);

    qglMatrixMode(GL_TEXTURE);
    qglLoadIdentity();

    qglDisable(GL_TEXTURE_GEN_S);
    qglDisable(GL_TEXTURE_GEN_T);
    qglDisable(GL_TEXTURE_GEN_R);
    qglDisable(GL_TEXTURE_GEN_Q);

    qglMatrixMode(GL_MODELVIEW);
}

void R_DrawShadows(void)
{
    for (int i = 0; i < numsdlights; i++)
    {
        cursdlight = &sdlights[i];

        if(!R_ShouldCastShadow())
            continue;

        R_SetupShadowLight();
        R_DrawSceneShadow();
        R_FinishShadowLight();
    }
}

您的阴影纹理坐标错过了阴影贴图计算和单个对象定位之间应用的逆模型视图变换ShadowCoord=gl_TextureMatrix[0]*invModelView*gl_ModelViewMatrix*gl_Vertex;我尝试过,但没有改变。我有一个想法,我们可以比较阴影贴图的深度和gl_顶点。xyz在灯光视图空间中的深度,如果gl_顶点的深度值远小于阴影贴图的深度值,这意味着有阴影的曲面离实体很远。阴影贴图查找可以进行深度比较,检查,或者查看不同的示例,这里有一个很好的例子:
//vertex shader
varying vec4 shadowcoord;

void main()
{
    shadowcoord = gl_TextureMatrix[0] * gl_Vertex;
    gl_Position = ftransform();
}

//fragment shader
#version 120
uniform sampler2DShadow shadowmap;
varying vec4 shadowcoord;

uniform float xoffset = 1.0/512.0;
uniform float yoffset = 1.0/512.0;

float lookup(vec4 coord, vec2 offSet)
{
    return shadow2DProj(shadowmap, coord + vec4(offSet.x * xoffset, offSet.y * yoffset, 0.0, 0.0) ).w;
}

void main()
{
    float shadow;
    shadow = lookup(shadowcoord, vec2(0.0,0.0)) + lookup(shadowcoord, vec2(0.035,0.0)) + lookup(shadowcoord, vec2(-0.035,0.0)) + lookup(shadowcoord, vec2(0.0,0.035)) + lookup(shadowcoord, vec2(0.0,-0.035));
    shadow /= 5.0;

    if(shadow == 1.0)
        discard;
    else
        gl_FragColor = vec4(0.0, 0.0, 0.0, (1.0-shadow) * 0.5);
}