Search code examples
c++openglglut

Adjusting light source size


I am currently trying to position a light starting from the bottom left of my screen and illuminating towards the center of my screen but my light source does not appear circular (light does not seem to be coming from a single point). enter image description here

After moving the light source it shines on the entire object but the desired effect is for the lightsource to only shine (based on a point) towards the right.

enter image description here

void init()
{
    camPos[0]= -(size/2)*.1;
    camPos[1]= size*.1;
    camPos[2]= -(size/2)*.1;
    zoom = size/10;
    glClearColor(0,0,0,0);
    glColor3f(1, 1, 1);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //Enable backface culling
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glFrontFace(GL_CW);  

    //Enable Lighting
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    light_pos[0] = 1;
    light_pos[1] = 10;
    light_pos[2] = 1;
    light_pos[3] = 1;

    gluPerspective(45, 1, 1, 100);

};

void display()
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //Camera
    radians =  float(pi*(angle-90.0f)/180.0f);
    //initialize look
    look[0] = (size/2)*.1;
    look[1] = 1;
    look[2] = (size/2)*.1;

    camPos[0] = look[0] + sin(radians)*zoom;
    camPos[1] = size/10;
    camPos[2] = look[2] + cos(radians)*zoom;

    gluLookAt(camPos[0], camPos[1], camPos[2], look[0],look[1],look[2], 0,1,0);
    //lighting
    //glColor3f(1,1,1);


    float m_amb[] = {0.2, 0.2, 0.2, 1.0};
    float m_dif[] = {1, 1, 1, 1.0};
    float m_spec[] = {1, 1, 1, 1.0};
    float shiny = 27;

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, m_amb);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, m_dif);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, m_spec);
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shiny);


    glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
    glShadeModel(GL_SMOOTH);
    drawTerrain(terrainA, size);
    glutSwapBuffers();

};

int main (int argc, char** argv)
{
    srand(time(NULL));
    //When program starts enter value

    printf("Enter an int between 50 and 300: ");
    scanf("%i",&size);

    if ( size < 50 || size > 300){
        printf("Invalid size! Please re-run \n");
        return 0;
    }
    populateArray();
    //Starts glut
    glutInit(&argc, argv);
    //Init display
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 800);
    glutInitWindowPosition(600, 100);
    glutCreateWindow("Terrain");glEnable(GL_DEPTH_TEST);
    //Registering Callbacks
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);

    glEnable(GL_DEPTH_TEST);
    init();

    glutMainLoop(); 


    return 0;
};

Solution

  • The general practic is to define light attenuation factors as a coeficients of light equation.

    enter image description here

    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.5);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.5);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.2);
    

    where kc is constant attenuation factor, kl - linear attenuation factor, kq - quadratic attenuation factor, d - distance to light source. You can modify this coeficients to achive the effect you want.

    This example could not works correctly so I suggest to build your own light destribution function using shaders, it will be simple to achive desired effect and more effective (and will always work).