(OpenGL ShadowMap)阴影投射在不正确的面孔上

时间:2015-03-09 06:40:45

标签: opengl glsl

这是演示图片:

shadow twice shadow on wrong faces

(左上角256x256 rect是深度纹理)

我在第一遍(平行投影)中渲染阴影贴图,

然后在第二遍中渲染场景

然后在最后一遍中使用阴影贴图渲染场景。

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

有没有解决方案?

完整代码:

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

GLSL部分:

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

0 个答案:

没有答案