opengl中处理光照和阴影的问题

发布于 2024-10-29 22:55:47 字数 8885 浏览 0 评论 0原文

我正在尝试将灯光、材质和阴影添加到我的机器人手臂上,但不幸的是发生了一些奇怪的事情(请编译或查看下图),现在我仍然很烦 weird 3d

1) 没有显示正确的光照和反射属性以及材质属性

2) 没有绘制阴影,尽管我已经完成了函数“void showobj(void)”中的阴影投射

我很感激如果有人可以提供帮助,我已经为此工作了 2 天但没有任何进展:(

以下是我的代码

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <GL/glut.h>
#include "gsrc.h"   
#include <Windows.h>

const double PI = 3.14159265;
// angles to rotate the base, lower and upper arms of the robot arm
static GLfloat theta, phi, psi = 0.0;
//Starting time
double startT;
//Time Diff variable
double dif,startTime,endTime,deltaT;
//define n
double n = 3;
//Set the parameters of the light number one
GLfloat Xs = 35.0;
GLfloat Ys = 35.0;
GLfloat Zs = 35.0;
//Shadow color
GLfloat shadowcolor[] = {0.0,0.0,0.0};

//initialize the window and everything to prepare for display
void init_gl() {
    //set display color to white
    glClearColor(1,1,1,0);
    //clear and enable z-buffer 
    glClear (GL_DEPTH_BUFFER_BIT);
    glEnable (GL_DEPTH_TEST);
    //clear display window
    glClear(GL_COLOR_BUFFER_BIT);
}

//Draw the base of the robot arm
void draw_base(){
    glPushMatrix();
        //to create the quadric objects
        GLUquadric *qobj,*qobjl,*qobju;
        qobj = gluNewQuadric(); 
        qobjl = gluNewQuadric(); 
        qobju = gluNewQuadric(); 

        //set the color of the cylinder
        glColor3f(1.0,0.0,0.0); 
        //Re-position the cylinder (x-z plane is the base)
        glRotatef(-90,1.0,0.0,0.0);
        //Draw the cylinder
        gluCylinder(qobj, 30.0, 30.0, 40.0, 40.0, 40.0);
        //Draw the upper disk of the base
        gluDisk(qobju,0,30,40,40);

        glPushMatrix();
            //Change the M(lowdisk<updisk)
            glTranslatef(0,0,40);
            glColor3f(0,0,0); 
            //Draw the lower disk of the base
            gluDisk(qobjl,0,30,40,40);
        glPopMatrix();
   glPopMatrix();
}

/***********************Texture Work Starts************************************/
//Load the raw file for texture
/* Global Declarations */
#define IW  256             // Image Width    
#define IH  256             // Image Height

//3D array to store image data
unsigned char InputImage     [IW][IH][4];  

// Read an input image from a .raw file with double
void ReadRawImage ( unsigned char Image[][IH][4] )
{
    FILE *fp;
    int  i, j, k;
    char* filename;
    unsigned char temp;

    filename = "floor.raw";

    if ((fp = fopen (filename, "rb")) == NULL)
    {
        printf("Error (ReadImage) : Cannot read the file!!\n");
        exit(1);
    }

    for ( i=0; i<IW; i++)
    {
        for ( j=0; j<IH; j++)
        {
            for (k = 0; k < 3; k++)       // k = 0 is Red  k = 1 is Green K = 2 is Blue
            {
                fscanf(fp, "%c", &temp);
                Image[i][j][k] = (unsigned char) temp;
            }
            Image[i][j][3] = (unsigned char) 0;         // alpha = 0.0
        }
    }
    fclose(fp);

}

/****************************Texture Work Ends***************************************/

/****************************Light and Shadows***************************************/
void lightsrc(){
GLfloat light1PosType [] = {Xs, Ys, Zs, 1.0};
    //GLfloat light2PosType [] = {0.0, 100.0, 0.0, 0.0};

    glLightfv(GL_LIGHT1, GL_POSITION, light1PosType);
    //glEnable(GL_LIGHT1);
    //glLightfv(GL_LIGHT2, GL_POSITION, light2PosType);
    //glEnable(GL_LIGHT2);

    GLfloat whiteColor[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat blackColor[] = {0.0, 0.0, 0.0, 1.0};
    glLightfv(GL_LIGHT1, GL_AMBIENT, blackColor);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, whiteColor);
    glLightfv(GL_LIGHT1, GL_SPECULAR, whiteColor);
    glEnable(GL_LIGHT1);

    glEnable( GL_LIGHTING );
}

/****************************Light and Shadows work ends***************************************/

//Draw the 2x2x2 cube with center (0,1,0)
void cube(){ 
    glPushMatrix();
        glTranslatef(0,1,0);
        glutSolidCube(2);
    glPopMatrix();  
}

//Draw the lower arm
void draw_lower_arm(){
    glPushMatrix();
    glScalef(15.0/2.0,70.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
    cube();
    glPopMatrix();
}

//Draw the upper arm
void draw_upper_arm(){
    glPushMatrix();
    glScalef(15.0/2.0,40.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
    cube();
    glPopMatrix();
}

void drawCoordinates(){
    glBegin (GL_LINES);
        glColor3f (1,0,0);
        glVertex3f (0,0,0);
        glVertex3f (600,0,0);

        glColor3f (0,1,0);
        glVertex3f (0,0,0);
        glVertex3f (0,600,0);

        glColor3f (0,0,1);
        glVertex3f (0,0,0);
        glVertex3f (0,0,600);
    glEnd();        
}

//To draw the whole robot arm
void drawRobot(){
    //Robot Drawing Starts
      //Rotate the base by theta degrees
      glRotatef(theta,0.0,1.0,0.0); 
      //Draw the base
      draw_base();
      //M(B<La)
      glTranslatef(0.0,40.0,0.0);
      //Rotate the lower arm by phi degree
      glRotatef(phi,0.0,0.0,1.0);
      //change the color of the lower arm
      glColor3f(0.0,0.0,1.0);
      //Draw the lower arm
      draw_lower_arm();
      //M(La<Ua)
      glTranslatef(0.0,70.0,0.0);
      //Rotate the upper arm by psi degree
      glRotatef(psi,0.0,0.0,1.0);
      //change the color of the upper arm
      glColor3f(0.0,1.0,0.0);
      //Draw the upper arm
      draw_upper_arm();
      //Drawing Finish
      glutSwapBuffers();
}

void showobj(void) {
   //set the projection and perspective parameters/arguments
    GLint viewport[4];
    glGetIntegerv( GL_VIEWPORT, viewport );
    glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective( 45, double(viewport[2])/viewport[3], 0.1, 1000 );
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      gluLookAt(-200, 300, 200, 0, 0, 0, 0,1,0 );
      // get the rotation matrix from the rotation user-interface
      glMultMatrixf(gsrc_getmo() );  
      //Clear the display and ready to show the robot arm
      init_gl();    

      //put the light source
      lightsrc();
      //Draw coordinates
      drawCoordinates();
      //give material properties
        GLfloat diffuseCoeff[] = {0.2, 0.4, 0.9, 1.0}; // kdR= 0.2, kdG= 0.4, kdB= 0.9
        GLfloat specularCoeff[] = {1.0, 1.0, 1.0, 1.0}; // 
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseCoeff);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularCoeff);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0 ); // ns= 25

      //Draw the ground floor
      glColor3f(0.4,0.4,0.4);
      glPushMatrix();
        glRotatef(90,1,0,0);
        glRectf(-500,-500,500,500);
      glPopMatrix();

        int i,j;
        GLfloat M[4][4];
        for (i=0; i<4; i++){
            for (j=0; j<4; j++){
                M[i][j] = 0;
            }
            M[0][0]=M[1][1]=M[2][2]=1;
            M[2][3]=-1.0/Zs;
        }

        //Start drawing shadow
        drawRobot(); // draw the objects
        glPushMatrix( ); // save state
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(Xs, Ys, Zs);// Mwc&#8592;s
        glMultMatrixf(M[4]);// perspective project
        glTranslatef(-Xs, -Ys, -Zs);// Ms&#8592;wc
        glColor3fv (shadowcolor);
        //Draw the robot arm
        drawRobot();
        glPopMatrix(); // restore state
        //Shadow drawing ends

      glFlush ();  
}

//To animate the robot arm
void animate(void)
{
    //get the end time
    endTime = timeGetTime();
    //float angle;
    //calculate deltaT 
    deltaT = (endTime - startTime); //in msecs
    //float test;
    float deltaTSecs = deltaT/1000.0f;  //in secs
    //apply moving equation 
    psi = (90.0) * 0.50 * (1-cos((deltaTSecs/(n+1)) * PI));
    glutPostRedisplay ();
}

void main (int argc, char** argv)
{ 
    glutInit(&argc, argv); 
    //DOUBLE mode better for animation
    // Set display mode.
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition( 50, 100 ); // Set top-left display-window position.
    glutInitWindowSize( 400, 300 ); // Set display-window width and height.
    glutCreateWindow( "Robot arm : my first self-learning opengl program" ); // Create display window.
    // Register mouse-click and mouse-move glut callback functions
    // for the rotation user-interface.
    //Allow user to drag the mouse and view the object
    glutMouseFunc( gsrc_mousebutton );
    glutMotionFunc( gsrc_mousemove );   
    //record the starting time
    startTime = timeGetTime();
    // Display everything in showobj function
    glutDisplayFunc(showobj); 
    //Perform background processing tasks or continuous animation
    glutIdleFunc(animate);
    glutMainLoop(); 
}

I am trying to put lights, materials and shadows to my robot arm but unfortunately something weird happens (please compile or see the below picture), now I am still annoying by
weird 3d

1) Not showing correct lighting and reflection properties as well as material properties

2) No shadow painted, although I have done the shadow casting in function "void showobj(void)"

I appreciate if anyone can help, I have already working for it 2 days with no progress :(

The following is my code

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <GL/glut.h>
#include "gsrc.h"   
#include <Windows.h>

const double PI = 3.14159265;
// angles to rotate the base, lower and upper arms of the robot arm
static GLfloat theta, phi, psi = 0.0;
//Starting time
double startT;
//Time Diff variable
double dif,startTime,endTime,deltaT;
//define n
double n = 3;
//Set the parameters of the light number one
GLfloat Xs = 35.0;
GLfloat Ys = 35.0;
GLfloat Zs = 35.0;
//Shadow color
GLfloat shadowcolor[] = {0.0,0.0,0.0};

//initialize the window and everything to prepare for display
void init_gl() {
    //set display color to white
    glClearColor(1,1,1,0);
    //clear and enable z-buffer 
    glClear (GL_DEPTH_BUFFER_BIT);
    glEnable (GL_DEPTH_TEST);
    //clear display window
    glClear(GL_COLOR_BUFFER_BIT);
}

//Draw the base of the robot arm
void draw_base(){
    glPushMatrix();
        //to create the quadric objects
        GLUquadric *qobj,*qobjl,*qobju;
        qobj = gluNewQuadric(); 
        qobjl = gluNewQuadric(); 
        qobju = gluNewQuadric(); 

        //set the color of the cylinder
        glColor3f(1.0,0.0,0.0); 
        //Re-position the cylinder (x-z plane is the base)
        glRotatef(-90,1.0,0.0,0.0);
        //Draw the cylinder
        gluCylinder(qobj, 30.0, 30.0, 40.0, 40.0, 40.0);
        //Draw the upper disk of the base
        gluDisk(qobju,0,30,40,40);

        glPushMatrix();
            //Change the M(lowdisk<updisk)
            glTranslatef(0,0,40);
            glColor3f(0,0,0); 
            //Draw the lower disk of the base
            gluDisk(qobjl,0,30,40,40);
        glPopMatrix();
   glPopMatrix();
}

/***********************Texture Work Starts************************************/
//Load the raw file for texture
/* Global Declarations */
#define IW  256             // Image Width    
#define IH  256             // Image Height

//3D array to store image data
unsigned char InputImage     [IW][IH][4];  

// Read an input image from a .raw file with double
void ReadRawImage ( unsigned char Image[][IH][4] )
{
    FILE *fp;
    int  i, j, k;
    char* filename;
    unsigned char temp;

    filename = "floor.raw";

    if ((fp = fopen (filename, "rb")) == NULL)
    {
        printf("Error (ReadImage) : Cannot read the file!!\n");
        exit(1);
    }

    for ( i=0; i<IW; i++)
    {
        for ( j=0; j<IH; j++)
        {
            for (k = 0; k < 3; k++)       // k = 0 is Red  k = 1 is Green K = 2 is Blue
            {
                fscanf(fp, "%c", &temp);
                Image[i][j][k] = (unsigned char) temp;
            }
            Image[i][j][3] = (unsigned char) 0;         // alpha = 0.0
        }
    }
    fclose(fp);

}

/****************************Texture Work Ends***************************************/

/****************************Light and Shadows***************************************/
void lightsrc(){
GLfloat light1PosType [] = {Xs, Ys, Zs, 1.0};
    //GLfloat light2PosType [] = {0.0, 100.0, 0.0, 0.0};

    glLightfv(GL_LIGHT1, GL_POSITION, light1PosType);
    //glEnable(GL_LIGHT1);
    //glLightfv(GL_LIGHT2, GL_POSITION, light2PosType);
    //glEnable(GL_LIGHT2);

    GLfloat whiteColor[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat blackColor[] = {0.0, 0.0, 0.0, 1.0};
    glLightfv(GL_LIGHT1, GL_AMBIENT, blackColor);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, whiteColor);
    glLightfv(GL_LIGHT1, GL_SPECULAR, whiteColor);
    glEnable(GL_LIGHT1);

    glEnable( GL_LIGHTING );
}

/****************************Light and Shadows work ends***************************************/

//Draw the 2x2x2 cube with center (0,1,0)
void cube(){ 
    glPushMatrix();
        glTranslatef(0,1,0);
        glutSolidCube(2);
    glPopMatrix();  
}

//Draw the lower arm
void draw_lower_arm(){
    glPushMatrix();
    glScalef(15.0/2.0,70.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
    cube();
    glPopMatrix();
}

//Draw the upper arm
void draw_upper_arm(){
    glPushMatrix();
    glScalef(15.0/2.0,40.0/2.0,15.0/2.0);//scale half is enough (some part is in the negative side)
    cube();
    glPopMatrix();
}

void drawCoordinates(){
    glBegin (GL_LINES);
        glColor3f (1,0,0);
        glVertex3f (0,0,0);
        glVertex3f (600,0,0);

        glColor3f (0,1,0);
        glVertex3f (0,0,0);
        glVertex3f (0,600,0);

        glColor3f (0,0,1);
        glVertex3f (0,0,0);
        glVertex3f (0,0,600);
    glEnd();        
}

//To draw the whole robot arm
void drawRobot(){
    //Robot Drawing Starts
      //Rotate the base by theta degrees
      glRotatef(theta,0.0,1.0,0.0); 
      //Draw the base
      draw_base();
      //M(B<La)
      glTranslatef(0.0,40.0,0.0);
      //Rotate the lower arm by phi degree
      glRotatef(phi,0.0,0.0,1.0);
      //change the color of the lower arm
      glColor3f(0.0,0.0,1.0);
      //Draw the lower arm
      draw_lower_arm();
      //M(La<Ua)
      glTranslatef(0.0,70.0,0.0);
      //Rotate the upper arm by psi degree
      glRotatef(psi,0.0,0.0,1.0);
      //change the color of the upper arm
      glColor3f(0.0,1.0,0.0);
      //Draw the upper arm
      draw_upper_arm();
      //Drawing Finish
      glutSwapBuffers();
}

void showobj(void) {
   //set the projection and perspective parameters/arguments
    GLint viewport[4];
    glGetIntegerv( GL_VIEWPORT, viewport );
    glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective( 45, double(viewport[2])/viewport[3], 0.1, 1000 );
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      gluLookAt(-200, 300, 200, 0, 0, 0, 0,1,0 );
      // get the rotation matrix from the rotation user-interface
      glMultMatrixf(gsrc_getmo() );  
      //Clear the display and ready to show the robot arm
      init_gl();    

      //put the light source
      lightsrc();
      //Draw coordinates
      drawCoordinates();
      //give material properties
        GLfloat diffuseCoeff[] = {0.2, 0.4, 0.9, 1.0}; // kdR= 0.2, kdG= 0.4, kdB= 0.9
        GLfloat specularCoeff[] = {1.0, 1.0, 1.0, 1.0}; // 
        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseCoeff);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularCoeff);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.0 ); // ns= 25

      //Draw the ground floor
      glColor3f(0.4,0.4,0.4);
      glPushMatrix();
        glRotatef(90,1,0,0);
        glRectf(-500,-500,500,500);
      glPopMatrix();

        int i,j;
        GLfloat M[4][4];
        for (i=0; i<4; i++){
            for (j=0; j<4; j++){
                M[i][j] = 0;
            }
            M[0][0]=M[1][1]=M[2][2]=1;
            M[2][3]=-1.0/Zs;
        }

        //Start drawing shadow
        drawRobot(); // draw the objects
        glPushMatrix( ); // save state
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(Xs, Ys, Zs);// Mwc←s
        glMultMatrixf(M[4]);// perspective project
        glTranslatef(-Xs, -Ys, -Zs);// Ms←wc
        glColor3fv (shadowcolor);
        //Draw the robot arm
        drawRobot();
        glPopMatrix(); // restore state
        //Shadow drawing ends

      glFlush ();  
}

//To animate the robot arm
void animate(void)
{
    //get the end time
    endTime = timeGetTime();
    //float angle;
    //calculate deltaT 
    deltaT = (endTime - startTime); //in msecs
    //float test;
    float deltaTSecs = deltaT/1000.0f;  //in secs
    //apply moving equation 
    psi = (90.0) * 0.50 * (1-cos((deltaTSecs/(n+1)) * PI));
    glutPostRedisplay ();
}

void main (int argc, char** argv)
{ 
    glutInit(&argc, argv); 
    //DOUBLE mode better for animation
    // Set display mode.
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition( 50, 100 ); // Set top-left display-window position.
    glutInitWindowSize( 400, 300 ); // Set display-window width and height.
    glutCreateWindow( "Robot arm : my first self-learning opengl program" ); // Create display window.
    // Register mouse-click and mouse-move glut callback functions
    // for the rotation user-interface.
    //Allow user to drag the mouse and view the object
    glutMouseFunc( gsrc_mousebutton );
    glutMotionFunc( gsrc_mousemove );   
    //record the starting time
    startTime = timeGetTime();
    // Display everything in showobj function
    glutDisplayFunc(showobj); 
    //Perform background processing tasks or continuous animation
    glutIdleFunc(animate);
    glutMainLoop(); 
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疯到世界奔溃 2024-11-05 22:55:47

你的屏幕闪烁是因为你在drawRobot()中调用了glutSwapBuffers()。这会使您的屏幕重绘两次,一次是在绘制机器人时,另一次是在绘制阴影时。另外,您在drawRobot()开头缺少glPushMatrix(),在结尾缺少glPopMatrix()。你需要把它放在那里,否则会影响之后的渲染(阴影会随着手臂的上连杆移动)。

那么,你指定的阴影矩阵是错误的。让我们试试这个:

    int i,j;
    GLfloat M[4][4];
    for (i=0; i<4; i++){
        for (j=0; j<4; j++){
            M[i][j] = 0;
        }
    }
    M[0][0]=M[1][1]=M[2][2]=1;
    M[2][3]=-1.0/Zs;

    drawRobot(); // draw the objects

    //Start drawing shadow
    glEnable(GL_CULL_FACE);
    glDisable(GL_LIGHTING); // want constant-color shadow
    glPushMatrix( ); // save state
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(Xs, Ys, Zs);// Mwc←s
        glMultMatrixf(&M[0][0]);// perspective project
        glTranslatef(-Xs, -Ys, -Zs);// Ms←wc
        glColor3fv (shadowcolor);
        //Draw the robot arm
        drawRobot();
    glPopMatrix(); // restore state
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHTING); // enable again ...
    //Shadow drawing ends

另外,你可以看到我在阴影周围添加了 GL_CULL_FACE,这是为了避免深度战斗。这或多或少在技术上修复了它。

但仍然 - 阴影位置计算不正确。让我们尝试查看投影阴影

因此,首先,我们需要确定地平面和灯光的位置:

float g[] = {0, 1, 0, 0}; // ground plane
float l[] = {20, 300, 50, 1}; // light position and "1"

这是一个平面方程和一个均匀的灯光位置(正常 3D 位置,用“1”填充)。然后你扔掉你的阴影矩阵设置(glTranslatef(),glMultMatrixf()和glTranslatef())并调用myShadowMatrix(g,l)来代替,所以它变成:

glPushMatrix( ); // save state
    glMatrixMode(GL_MODELVIEW);
    float g[] = {0, 1, 0, 0}; // ground plane
    float l[] = {20, 300, 50, 1}; // light position and "1"
    myShadowMatrix(g, l);
    glColor3fv (shadowcolor);
    //Draw the robot arm
    drawRobot();
glPopMatrix(); // restore state

这基本上有效。仍然有很多 z-fighting 正在进行,并且阴影有四种不同的颜色。至于颜色,停止在drawRobot()中调用glColor3f(),至于z-fighting,使用这个:

glPolygonOffset(-1, -1);
glEnable(GL_POLYGON_OFFSET_FILL);
// before

// draw shadow

glDisable(GL_POLYGON_OFFSET_FILL);
// afterwards

这就是一个漂亮的平面阴影演示:)。干杯...

sw。

your screen flashes because you are calling glutSwapBuffers() in drawRobot(). That makes your screen repaint two times, once when you draw the robot, and once more when you draw the shadow. Also, you are missing glPushMatrix() at the beginning of drawRobot() and glPopMatrix() at the end. You need to put it there, otherwise it will affect rendering afterwards (the shadow will move with the upper link of the arm).

Then, you specify the shadow matrix wrong. Let's try this:

    int i,j;
    GLfloat M[4][4];
    for (i=0; i<4; i++){
        for (j=0; j<4; j++){
            M[i][j] = 0;
        }
    }
    M[0][0]=M[1][1]=M[2][2]=1;
    M[2][3]=-1.0/Zs;

    drawRobot(); // draw the objects

    //Start drawing shadow
    glEnable(GL_CULL_FACE);
    glDisable(GL_LIGHTING); // want constant-color shadow
    glPushMatrix( ); // save state
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(Xs, Ys, Zs);// Mwc←s
        glMultMatrixf(&M[0][0]);// perspective project
        glTranslatef(-Xs, -Ys, -Zs);// Ms←wc
        glColor3fv (shadowcolor);
        //Draw the robot arm
        drawRobot();
    glPopMatrix(); // restore state
    glDisable(GL_CULL_FACE);
    glEnable(GL_LIGHTING); // enable again ...
    //Shadow drawing ends

Also, you can see i've added GL_CULL_FACE arround the shadow, it is to avoid depth fighting. This more or less fixes it technically.

But still - the shadow position is calculated incorrectly. Let's try looking at projection shadows.

So first, we need to have position for the ground plane and for the light:

float g[] = {0, 1, 0, 0}; // ground plane
float l[] = {20, 300, 50, 1}; // light position and "1"

That is a plane equation and a homogenous light position (normal 3D position, padded with a "1"). Then you throw away your shadow matrix setup (glTranslatef(), glMultMatrixf() and glTranslatef()) and call myShadowMatrix(g, l) instead, so it becomes:

glPushMatrix( ); // save state
    glMatrixMode(GL_MODELVIEW);
    float g[] = {0, 1, 0, 0}; // ground plane
    float l[] = {20, 300, 50, 1}; // light position and "1"
    myShadowMatrix(g, l);
    glColor3fv (shadowcolor);
    //Draw the robot arm
    drawRobot();
glPopMatrix(); // restore state

And that mostly does work. There is still a lot of z-fighting going on, and the shadow has four different colors. As for the colors, stop calling glColor3f() in drawRobot(), as for the z-fighting, use this:

glPolygonOffset(-1, -1);
glEnable(GL_POLYGON_OFFSET_FILL);
// before

// draw shadow

glDisable(GL_POLYGON_OFFSET_FILL);
// afterwards

And that makes one nice planar shadows demo :). Cheers ...

sw.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文