0
\$\begingroup\$

I've a problem with shadow (Stencil). So when i draw the shadow they looks good, but when the object to draw is underground his shadow is wrongly rendered. My game is do with LWJGL/GL11.

Normal render: over http://web-survival-machines.crystal-serv.com/shadow%20problem%201.jpg Bad renders: over http://web-survival-machines.crystal-serv.com/shadow%20problem%202.jpg over http://web-survival-machines.crystal-serv.com/shadow%20problem%203.jpg

the light is on the right of the scene.

code used to render:

public void render(){
    TimeLogic.updateMSTimer(); TimeLogic.updateDelta();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    glLight(GL_LIGHT0, GL_POSITION, BufferUtils.arrayToBufferFloat(lightPos));


    //-----

    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_ALWAYS, 1, ~0);
    glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
    drawScene();
    /*do->
    glPushMatrix();
        glTranslatef(0,(float)(Math.sin((float)(Sys.getTime())*0.002f))*2+1, 0);
        sphere.draw(1, 70, 20);
    glPopMatrix();

    SimpleEntities.drawBox(50, 0.25f, 50);
    */

    //-----

    glDisable(GL_STENCIL_TEST);

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_EQUAL, 1, ~0);
    glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO);

    glEnable(GL_BLEND);//Turn blending on
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_LIGHTING);//Turn off light to draw shadow without normals
    glColor4f(0.0f,0.0f,0.0f,0.5f);//Exsisting color (on plane) is modulated with 50% black


    //-----

    //Draw shadow of objects on the floor
    glEnable(GL_DEPTH_TEST);

    drawSceneShadow();
    /*do->
    glPushMatrix();
        glTranslatef(0, 0.0005f, 0);
        glMultMatrix(BufferUtils.arrayToBufferFloat(shadow_floor));
        drawSphere();
    glPopMatrix();
    */
    //-----

    //Restore original mode
    glDisable(GL_BLEND);
    glDisable(GL_STENCIL_TEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    //-----


    updateCam();//check keys and do a gluLookAt();

    Display.update();
    Display.sync(GameInfo.FPS);//--> 60FPS

    TimeLogic.showFPS();

    if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
        //pauseMenuShow = true;
        //showPauseMenu();
        render = false;
        Display.destroy();
    }
}

SimpleEntities.drawBox function:

public static void drawBox(float x, float y, float z){
    // cut the quad in parts for light reflection

    float cutx = 0;
    for(float i=0;i<x;i+=cutSize){
        cutx++;
    }
    float cuty = 0;
    for(float i=0;i<y;i+=cutSize){
        cuty++;
    }
    float cutz = 0;
    for(float i=0;i<z;i+=cutSize){
        cutz++;
    }
    //-------------------------
    glPushMatrix();
    glScalef(x,y,z);
    glBegin (GL_QUADS);

    //glColor3f(1, 1, 0);
    //face 1 
    glNormal3f(-1, 1,-1);
    glVertex3f(-1, 1,-1); glVertex3f( 1, 1,-1);
    glVertex3f( 1,-1,-1); glVertex3f(-1,-1,-1);
    //face 2 bottom
    glNormal3f(-1,-1,-1);
    glVertex3f(-1,-1,-1); glVertex3f( 1,-1,-1);
    glVertex3f( 1,-1, 1); glVertex3f(-1,-1, 1);
    // face 3 
    glNormal3f( 1,-1, 1);
    glVertex3f( 1,-1, 1); glVertex3f( 1,-1,-1);
    glVertex3f( 1, 1,-1); glVertex3f( 1, 1, 1);

    //face 4 top
    //--> x;z
    //System.out.println("number of part:\nx:"+cutx+"\ny:"+cuty+"\nz:"+cutz+"\n-----------------------");
    boolean first = true;
    for(float ix=0;ix<cutx;ix++){
        for(float iz=0;iz<cutz;iz++){
            /*
            glColor3f(30, 30, 30);
            if(first){
                glColor3f(255, 0, 0);
                first = false;
            }
            if(ix+1 == cutx && iz+1 == cutz){
                glColor3f(0, 255, 0);
                first = false;
            }
            */
            //-1 ==> i/cutx*2-1
            //1  ==> i/(cutx+1)*2-1
            /*
            System.out.println("-------------------------");
            System.out.println("iz="+iz);
            System.out.println("cutz="+cutz);
            System.out.println("=>"+iz+"/"+cutz+"*2-1");
            System.out.println("=>"+div+"*2-1");
            System.out.println("=>"+(div*2)+"-1");
            System.out.println("=>"+(div*2-1));
            System.out.println("-------------------------");
            */
            //System.out.println("-1 => "+iz+"/"+cutz+"*2-1 = "+n1);
            //System.out.println("1  => ("+iz+"/"+cutz+"+1)*2-1 = "+(iz/(cutz+1)*2-1));
            //float milis = (float)Math.sin(((double)System.currentTimeMillis())/5000);

            float overx = (ix+1)/cutx-0.5f;
            float underx = ix/cutx-0.5f;
            float overz = (iz+1)/cutz-0.5f;
            float underz = iz/cutz-0.5f;

            /*
            float overx = (ix+1)/cutx;
            float underx = ix/cutx;
            float overz = (iz+1)/cutz;
            float underz = iz/cutz;
            */
            glNormal3f(overx*2, 1, underz*2);
            glVertex3f(overx*2, 1, underz*2); glVertex3f(underx*2, 1, underz*2);
            glVertex3f(underx*2, 1, overz*2); glVertex3f(overx*2, 1, overz*2);
        }
    }
    //glNormal3f( 1, 1,-1);
    //glVertex3f( 1, 1,-1); glVertex3f(-1, 1,-1);
    //glVertex3f(-1, 1, 1); glVertex3f( 1, 1, 1);
    //face 5 
    glNormal3f(-1, 1, 1);
    glVertex3f(-1, 1, 1); glVertex3f(-1, 1,-1);
    glVertex3f(-1,-1,-1); glVertex3f(-1,-1, 1);
    //face 6 
    glNormal3f( 1,-1, 1);
    glVertex3f( 1,-1, 1); glVertex3f( 1, 1, 1);
    glVertex3f(-1, 1, 1); glVertex3f(-1,-1, 1);
    glEnd();
    glPopMatrix(); 
}

Can someone help me to resolve this bug ? thanks !

Sorry for my bad english --'

\$\endgroup\$
0
\$\begingroup\$

You are drawing the shadow using a cone from the light source which extends above the object causing the wrong shadow when the object is below ground.

You need to draw volumetric shadows by extending the shadow-casting object in the direction opposite to the light source, capped at the object.

Google "Volumetric Shadows" or "Shadow volume".

http://en.wikipedia.org/wiki/Shadow_volume

enter image description here

Notice that the shadow volumes don't extend toward the light, only away from it (light cap).

http://http.developer.nvidia.com/GPUGems/gpugems_ch09.html

enter image description here

\$\endgroup\$
  • \$\begingroup\$ I've found the Nehe tutorial converted for lwjgl (link). Do you think it's a good choise ? or can I only add one or two lines to make this doing right ? \$\endgroup\$ – Hugo Flores - Slaynash Jan 4 '15 at 13:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.